Method Swizzling

195 阅读1分钟

` +(void)load{

    /// 执行一次是为了确保不会因为手动调用load方法,而将方法又交换回来.

    static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            SEL swizzleSel = @selector(dd_viewDidAppear:);

            SEL originSel = @selector(viewDidAppear:);

            /// 当前类是一个继承自UIViewController的名叫TestController的类.

            Class aClassName = [TestController class];

            Method swizzleMethod = class_getInstanceMethod(aClassName, swizzleSel);

            Method originMethod = class_getInstanceMethod(aClassName, originSel);

           ///给当前类的originSel方法添加一个实现,如果TestController没有实现(重写)originSel,那么class_addMethod会添加成功.

            ///假设不class_addMethod,直接method_exchangeImplementations的话会如何?由于originSel并没有实现,所以method_exchangeImplementations中originMethod的实现可能是其父类(即UIViewController)的实现(在当前类未找到会去其父类寻找),此时你可能替换了UIViewController的对应方法的实现,还有一种假设,当前方法定义了但未被实现,假如直接method_exchangeImplementations那么在调用originSel的时候程序肯定会由于unrecognized selector而crash,该方法未定义的时候就不用讨论了,未定义你根本无法调用.

           BOOL success = class_addMethod(aClassName, originSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));

            if (success) {

                /// 调用swizzleSel的时候就会调用originMethod(即原originSel的实现)

                class_replaceMethod(aClassName, swizzleSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));

            }else{

                ///直接交换方法的实现

                method_exchangeImplementations(swizzleMethod,originMethod);

            }

        });

}`