Objective-C Runtime (一)

感受

淡到runtime ,让我们先感受一下它的黑魔法,欺诈(swizz),先写一点代码,感受一下

  • 1.新建一个项目, SingleViewApplication 然后选择默认的ViewController.m

  • 2.一个APP 运行的时候会先将类 load 到内存中,相当于电脑程序启动的时候,将程序资源从硬盘放到内存中一样

  • 3.包含头文件 既然要使用runtime ,那就要包含头文件 obj/runtime.h

  • 4.在 ViewController.m 文件,重写父类方法 + (void)load

  • 5.写下如下代码


+ (void)load{

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        Class class = [self class];

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

        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);
        }

    });
}
  • 6.然后重写继承的一个方法
    //view 即将显示的时候调用,一般不要在这个方法中写太多代码,这里用于测试
    - (void)viewWillAppear:(BOOL)animated{

        NSLog(@"viewWillAppear 哈哈");

        [super viewWillAppear:animated];
    }
  • 7.增加一个自己的方法 hehe:
    - (void)hehe:(BOOL)animated{
        NSLog(@"hehe 呵呵");
    }

好了,让我们command + R 吧,编译运行,输出结果为

这里写图片描述

没看错,并没有运行 * viewWillAppear:(BOOL)animated * 这里面的代码

让我们在见证一下在 viewDidLoad 手动调用viewWillAppear: 这个方法

- (void)viewDidLoad {
    [super viewDidLoad];
    //手动调用
    [self viewWillAppear:YES];
}

看看运行结果

这里写图片描述

结论

好像 viewWillAppear: 这个方法的代码永远不会被执行一样,但是却响应了这个消息viewWillAppear,只是执行的代码是hehe:方法中的代码,那么原因是什么?
在该类被加载到内存的时候也就是第一次 +load 的时候,使用了几个C语言的函数,将viewWillAppear消息(消息的名字不是这个)在运行时态对应的方法,给替换了,那么当消息循环收到这个消息的时候,就自己寻找到了对应的方法执行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章