iOS如何在不进行子类化的情况下将自定义代码添加到类方法中?

时间:2014-07-31 18:17:36

标签: ios objective-c inheritance polymorphism nsurlcache

如果我在我的应用中使用核心iOS类,例如NSURLCache;我希望在[[NSURLCache sharedURLCache] removeAllCachedResponses]被调用时随时打印一条日志消息。 如何在没有显式子类化NSURLCache的情况下扩展类方法,并用自定义类替换项目中的所有引用?有没有办法在类别中执行此操作?

1 个答案:

答案 0 :(得分:3)

您可以使用Method Swizzling执行此操作。这是a page with a nice overview of the technique,我借用了下面的大部分代码:

@interface SwizzleNSURLCache : NSURLCache
+(void)load;
-(void)swzl_removeAllCachedResponses;
@end

+(void)load {
    Class class = [SwizzleNSURLCache class];
    SEL originalSelector = @selector(removeAllCachedResponses);
    SEL swizzledSelector = @selector(swzl_removeAllCachedResponses);

    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

    BOOL didAddMethod = class_addMethod(class,
        originalSelector,
        method_getImplementation(swizzledMethod),
        method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(class,
            swizzledSelector,
            method_getImplementation(originalMethod),
            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

-(void) swzl_removeAllCachedResponses {
    // This is your replacement method. You can do whatever you want here.
    NSLog(@"Running removeAllCachedResponses");
    // If you need to call the actual implementation, do it like this:
    [self swzl_removeAllCachedResponses];
}

您不需要将NSURLCache的引用替换为此子类。您只需从程序中的某个位置加载一次即可。

注意:我不确定是否有更简单的方法。方法调整肯定是一个重型火炮,但它完成了工作。