美文网首页
iOS复习之RunTime

iOS复习之RunTime

作者: 小草先生 | 来源:发表于2017-10-19 22:32 被阅读24次

    1. 对象、类对象、元类对象
    2. 消息传递机制
    3. 消息转发流程
    4. Method Swizzling (交换方法)
    5. class_addMethod (动态添加方法)
    6. objc_getAssociatedObject objc_setAssociatedObject

    RunTime 

    主要 RunTime文章:

    Objective-C特性:Runtime
    让你快速上手Runtime
    iOS 程序员 6 级考试(答案和解释)

    Swift RunTime 视频:
    Swift RunTime

          OC是一门弱类型语言、动态语言,区别于C语言等面向过程编程(编译时就确定了调用哪个函数),区别于Swift强类型语言编译时有语法错误会实时提示,OC一些隐藏的BUG不会提示(如URL为空等情况)。OC编译时并不确定调用哪个函数,运行时才确定调用哪个函数,即SEL(函数编号)编译时不确定调用哪个IMP(函数指针),SEL -> IMP(映射关系)。
          我们一般用OC动态特性使用一些RunTime黑魔法,如交换方法,动态添加属性,动态添加方法,RunTime底层使用C进行一层封装,OC方法再对RunTime进行一层封装。

    1、消息传递机制

    导入头文件 #import <objc/message.h>,Build Settings 中 Enable Strict Checking of objc_msgSend Calls 至为NO。

    创建类Person,实现eat方法,调用eat方法的几种方式:
    1> Person *person = [[Person alloc] init]; [person eat];
    2> [person performSelector:@selector(eat)];
    3> objc_msgSend(person,@selector(eat));

    堆栈区别:
    堆:程序员自己alloc手动创建的。
    栈:系统分配的。


    导入头文件  #import <objc/runtime.h> 

    2、交换方法

    获取SEL函数编号:
    sel_registerName("") -> SEL
    NSSelectorFromString(@"") -> SEL

    获取类:
    NSClassFromString(@"") -> Class
    objc_getClass("") -> Class

    //  APP在手机的硬盘里,当加载类到内存的时候调用load方法
    + (void)load;

    获取类方法:
    class_getClassMethod(self, @selector(imageWithName:)) -> Method

    获取类对象方法(实例方法)
    class_getInstanceMethod(Class,SEL)

    // 交换两个方法的实现,一般用于给系统自带方法添加额外的方法
    method_exchangeImplementations(Method_Nonnull m1, Method_Nonnull m2)

    3、动态添加方法

    1) Q:子类继承父类的方法,子类里面有父类的方法吗?
    A:没有,系统查找子类中没有该方法时,会往上查找子类的父类。只有子类override(重载、重写)时才有这个方法,调用super继承父类的属性行为。

    // 当这个类调用了一个没有实现的类方法,可动态添加方法
    +(BOOL)resolveClassMethod:(SEL)sel;

    // 当这个类调用了一个没有实现的实例方法,可动态添加方法
    +(BOOL)resolveInstanceMethod:(SEL)sel;

    // 动态添加eat方法
    // 第一个参数:给哪个类添加方法
    // 第二个参数:添加方法的方法编号
    // 第三个参数:添加方法的函数实现(函数地址)
    // 第四个参数:函数的类型,(返回值+参数类型) v:void @:对象->self :表示SEL->_cmd

    class_addMethod(self, @selector(eat), eat, "v@:");

    4.给分类添加属性

    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"小码哥"; // Set
    NSLog(@"%@",objc.name); // Get

    // 定义关联的key
    static const char *key = "name";

    - (NSString *)name
    {
         // 根据关联的key,获取关联的值。
         return objc_getAssociatedObject(self, key);
    }

    - (void)setName:(NSString *)name
    {
         // 第一个参数:给哪个对象添加关联
         // 第二个参数:关联的key,通过这个key获取
         // 第三个参数:关联的value
         // 第四个参数:关联的策略

         objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    相关文章

      网友评论

          本文标题:iOS复习之RunTime

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