方法调配对NSFileHandle类不起作用

时间:2013-01-25 09:34:22

标签: ios objective-c

我有以下代码进行方法调配:

static inline void swizzleMethod(const char *clsName, const char *mthName, const char *clsName2, const char *mthName2) {
    Class cls1 = objc_getClass(clsName);
    SEL sel1 = sel_registerName(mthName);

    Class cls2 = objc_getClass(clsName2);
    SEL sel2 = sel_registerName(mthName2);
    Method mth = class_getInstanceMethod(cls2, sel2);
    IMP imp = method_getImplementation(mth);
    NSLog(@"method type encoding %s", method_getTypeEncoding(mth));

    class_replaceMethod(cls1, sel1, imp, method_getTypeEncoding(mth));
}

我的VGFileHandle课程:

@interface VGFileHandle : NSObject
@end

@implementation VGFileHandle
- (NSData *)readDataToEndOfFile {
    NSLog(@"readDataToEndOfFile");
    return nil;
}
@end

在main.m中,我有以下电话:

int main(int argc, char *argv[])
{    
    swizzleMethod("NSFileHandle", "readDataToEndOfFile", "VGFileHandle", "readDataToEndOfFile");

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"myFile"];

    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:filePath];
    NSData *data = [handle readDataToEndOfFile];

    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

右边,当调用[handle readDataToEndOfFile]时,它应该从VGFileHandle调用readDataToEndOfFile并打印出“readDataToEndOfFile”。但是,在我的测试项目中,似乎旋转方法根本不会取代方法实现。 [handle readDataToEndOfFile]仍然执行原始实现。

我想知道可能是什么原因。提前谢谢。

2 个答案:

答案 0 :(得分:2)

如果不看NSFileHandle的实现,就不可能明确地说出来。

最有可能的原因是,NSFileHandle是作为类集群实现的,因此,您实际上并不是抽象,公共类的实例。相反,你有一个私有子类的实例(可能因为看似随机,面向实现细节,跨OS版本或配置的原因而改变)。

Swizzling方法是错误的代码。私有系统类中的混合方法是更糟糕的代码,并且几乎可以保证导致调试和支持痛苦。

答案 1 :(得分:1)

[NSFileHandle fileHandleForReadingAtPath:filePath]将返回NSConcreteFileHandle的实例,而不是NSFileHandle。

你需要改为调用它:

swizzleMethod("NSConcreteFileHandle", "readDataToEndOfFile", "VGFileHandle", "readDataToEndOfFile");