Method Swizzling

目的:指透明的把一个东西换成另一个。在运行时替换。
利用方法混写可以改变那些没有源代码的对象。

该方法大致可以划分为三种:
1)有可能类已经实现的了
2)某个父类实现的方法
3)根本没有实现

前两种 可以通过调用class_getInstanceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>),成功后会返回一个IMP ,失败则是NULL。

最后一种 可以通过调用class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>) 如果失败,则此类直接实现了正在混写的方法,那么转而用method_setImplementation(<#Method m#>, <#IMP imp#>)来把就实现替换为新的实现即可。

#import 

@implementation UIViewController (Tracking)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(xxx_viewWillAppear:);

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

        // When swizzling a class method, use the following:
        // Class class = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(class, originalSelector);
        // Method swizzledMethod = class_getClassMethod(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);
        }
    });
}

#pragma mark - Method Swizzling

- (void)xxx_viewWillAppear:(BOOL)animated {
    [self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}

@end

你可能感兴趣的:(Method Swizzling)