美文网首页
iOS runtime

iOS runtime

作者: Jessica124 | 来源:发表于2018-03-12 15:15 被阅读5次

    runtime概念

    • runtime(简称运行时),是一套 纯C(C和汇编写的) 的API。而 OC 就是 运行时机制,也就是在运行时候的一些机制,其中最主要的是 消息机制

    runtime在项目中应用

    1、给分类(category)加属性

    在分类中添加方法比较常用,看到有些文章说不能为分类添加属性,实际上是可以实现的,具体demo
    可参考: https://www.jianshu.com/p/650bfdf12d11

    2、黑魔法:method swizzling

    Method Swizzling本质上就是对IMP和SEL进行交换。

    //头文件需导入#import <objc/runtime.h>
    - (void)hookMethod:(SEL)oldSEL newSEL:(SEL) newSEL {
        if (! oldSEL) {
            return;
        }
        if (! newSEL) {
            return;
        }
        Method oldMethod = class_getInstanceMethod([self class], oldSEL);
        assert(oldMethod);
        Method newMethod = class_getInstanceMethod([self class], newSEL);
        assert(newMethod);
        BOOL addSuccess = class_addMethod([self class], newSEL, newMethod, nil);
        if (addSuccess) {
            method_exchangeImplementations(oldMethod, newMethod);
        }
    }
    
    • 由于方法交换之后才能有效,所以如果想程序运行后方法就被执行,可将方法写在+load方法中.
      可以应用在AppDelegate瘦身(分类中实现部分方法)、面向切面编程逻辑(检测页面浏览、按钮点击日志),夜间模式、数组越界、字典用不存在的key取值等造成crash的情况,如果想默默的把crash规避掉..
      可参考:https://www.jianshu.com/p/ff19c04b34d0
    3、动态添加方法
    • 用@selector调用方法时,即使这个方法没有实现,编译器也不会报错,只会报个warnning,运行时就会crash,如果想处理这个crash..
      首先了解下消息的转发机制,就是按照下图进行的消息转发:
      消息转发.jpeg
      我们在 +(BOOL)resolveInstanceMethod:(SEL)name 这个类方法中处理.
    - (void)viewDidLoad {
        [super viewDidLoad];   
        Person *p = [[Person alloc] init];
        // 默认person,没有实现run:方法,可以通过performSelector调用,但是会报错。
        // 动态添加方法就不会报错
        [p performSelector:@selector(run:) withObject:@10];
    }
    
    @implementation Person
    // 没有返回值,1个参数
    // void,(id,SEL)
    void aaa(id self, SEL _cmd, NSNumber *meter) {
        NSLog(@"跑了%@米", meter);
    }
    
    // 任何方法默认都有两个隐式参数,self,_cmd(当前方法的方法编号)
    // 什么时候调用:只要一个对象调用了一个未实现的方法就会调用这个方法,进行处理
    // 作用:动态添加方法,处理未实现
    + (BOOL)resolveInstanceMethod:(SEL)sel
    {
        // [NSStringFromSelector(sel) isEqualToString:@"run"];
        if (sel == NSSelectorFromString(@"run:")) {
            // 动态添加run方法
            // class: 给哪个类添加方法
            // SEL: 添加哪个方法,即添加方法的方法编号
            // IMP: 方法实现 => 函数 => 函数入口 => 函数名(添加方法的函数实现(函数地址))
            // type: 方法类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd
            class_addMethod(self, sel, (IMP)aaa, "v@:@");
            return YES;
        }
        return [super resolveInstanceMethod:sel];
    }
    @end
    
    // 打印输出
    2016-02-17 19:05:03.917 runtime[12761:543574] runtime动态添加方法--跑了10米
    
    4、字典转模型MJKeyValue

    相关文章

      网友评论

          本文标题:iOS runtime

          本文链接:https://www.haomeiwen.com/subject/skenfftx.html