iOS 开发者的日常iOS Developer开发进阶 Runtime

深入浅出Objective-C 运行时黑魔法 method sw

2017-01-12  本文已影响62人  KenZhangCn

我们经常会浏览到关于method swizzling的文章, 都称之为黑魔法. 但是网络上各路大神的文章都很深奥, 本文我就以自己的理解深入浅出的解析一下这个黑魔法, 力求看了都能理解这个所谓的 "黑魔法"究竟是什么.


最近公司的项目遇到一个需求, 要在每一个viewWillDisappear时做一个操作, 调用一句代码. 看到这个需求时我就想起了之前遇过的黑魔法method swizzling;

@implementation UIViewController (swizzling)

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

        SEL originalSelector = @selector(viewWillDisappear:);  //初始化SEL类型对象指向viewWillDisappear:
        SEL swizzledSelector = @selector(XXX_viewWillDisappear:); //初始化SEL类型对象指向XXX_viewWillDisappear:

        //viewWillDisappear:对应的Method, 为类方法列表中originalSelector指向的方法实现
        Method originalMethod = class_getInstanceMethod(class, originalSelector); 
        //XXX_viewWillDisappear:对应的Method, 为类方法列表中swizzledSelector指向的方法实现
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        /*
        在类中增加方法: 方法名为originalSelector(即viewWillDisappear:), 
        对应的方法实现为swizzledMethod的实现(即XXX_viewWillDisappear:对应的实现)
        */
        BOOL didAddMethod =
            class_addMethod(class,
                originalSelector,
                method_getImplementation(swizzledMethod),
                method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod) {
        /*
        替换类中方法实现: 方法名为swizzledSelector(即XXX_viewWillDisappear:), 
        替换为为originalMethod的实现(即viewWillDisappear:对应的实现)
        */ 
            class_replaceMethod(class,
                swizzledSelector,
                method_getImplementation(originalMethod),
                method_getTypeEncoding(originalMethod));
        } else {
            //直接调换originalMethod和swizzledMethod方法的实现
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling

- (void)XXX_viewWillDisppear:(BOOL)animated { 
    //在VC中调用`viewWillDisppear`实际是调用了这里的实现
    [self XXX_viewWillDisppear:animated];  //这一句代码, 实际上是调用`viewWillDisppear`到实现
    NSLog(@"viewWillDisappear: %@", self);
}

@end

参考文章:
http://nshipster.cn/method-swizzling/
http://www.cocoachina.com/ios/20141031/10105.html
http://blog.jobbole.com/45963/
文章整理参考网络文章,如有错误,欢迎讨论指出。

上一篇下一篇

猜你喜欢

热点阅读