美文网首页
iOS---Runtime

iOS---Runtime

作者: jeff_guan | 来源:发表于2017-10-09 17:24 被阅读0次

RunTime

runtime 是什么

  • runtime ,运行时机制,是一套底层 C 语言的 API,其为 iOS 内核的一部分。
  • runtime 会把我们的 Objc 代码全部转换成 C 语言。

Runtime 的相关知识

  1. SEL

    • 方法选择器,对方法进行包装,然后找到方法对应的实现。
    • 其实它就是个映射到方法的 C 字符串
    • 其结构是typedef struct objc_selector *SEL;
    • 可以用 Objective-C 编译器命令 @selector() 或者 Runtime 系统的 sel_registerName 函数来获得一个 SEL 类型的方法选择器
  2. id

    • id 是一个结构体指针类型,它可以指向 Objective-C 中的任何对象。
    • 其结构是 struct objc_object { Class isa OBJC_ISA_AVAILABILITY;}
    • 其中 isa 指针是指向对象的类
  3. Class

其结构是

   struct objc_class {
   Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
   Class super_class   OBJC2_UNAVAILABLE; //指向其超类。
   const char *name   OBJC2_UNAVAILABLE; //类名
   long version     OBJC2_UNAVAILABLE; //类的版本信息
   long info     OBJC2_UNAVAILABLE; //类的详情
   long instance_size   OBJC2_UNAVAILABLE; //该类的实例对象的大小
   struct objc_ivar_list *ivars  OBJC2_UNAVAILABLE;  //成员列表
   struct objc_method_list **methodLists  OBJC2_UNAVAILABLE;  //方法列表
   struct objc_cache *cache    OBJC2_UNAVAILABLE;  //缓存
   struct objc_protocol_list *protocols   OBJC2_UNAVAILABLE;   //协议列表
#endif
} OBJC2_UNAVAILABLE;
  1. Method
    • method_types,存放方法的参数类型和返回值类型
    • IMP 指向的是方法的实现,本质是一个函数指针
typedef struct objc_method *Method;
struct objc_method
{
    SEL method_name   ;
    char *method_types  ;
    IMP method_imp   ;
}

一个对象方法的调用的过程

  1. runtime 把我们调用的方法转化为 objc_msgSend,然后把方法的调用者和方法选择器当作参数传递过去。
  2. 通过调用者的 isa 指针,找到对应的类。
  3. 先看看当前类的 cache 中有没有该方法的调用记录,有就指直接加载,通过方法的 IMP 指针找到方法对应的实现。
  4. 如果 cache 没有,就在 methodList 找该方法。
  5. 如果该类中找不到对应的方法,就往父类找,直到 NSObject 这个类。
  6. 到 NSObject 还没有找到该类,就会进入动态方法解析。

消息转发过程

调用一个不存在的方法,程序就会 crash,在程序进入 crash 之前,会有一个消息转发的过程,如果方法还是没有被处理,程序才会 crash。

  1. 进入 resolveInstanceMethod:resolveClassMethod: 方法---动态方法解析,如果这两个方法返回的是 nil,进入下一步。
  2. 进入 forwardingTargetForSelector: 方法---对象重定向,用于指定对象来响应这个 SEL,若返回的是 self 或者是 nil ,则进入下一步消息转发。
  3. 我们首先要通过 methodSignatureForSelector: 来指定方法签名,若返回 nil,表示不处理,不会进入消息转发机制;若返回方法签名,则会进入下一步。
  4. methodSignatureForSelector: 方法返回方法签名后,就会调用 forwardInvocation: 方法---消息转发,我们可以通过 anInvocation 对象做很多处理,比如修改实现方法,修改响应对象等。

动态方法解析

+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
    if (aSEL == @selector(resolveThisMethodDynamically)) {
          class_addMethod([self class], aSEL, (IMP)
dynamicMethodIMP, "v@:");
          return YES;
}
    return [super resolveInstanceMethod:aSEL];
}

- (void)dynamicMethodIMP{
     do something;
}

说明一下
class_addMethod(Class cls, SEL name, IMP imp, const char *types) 中的参数

  • Class cls:类,哪个类去调用
  • SEL name:方法选择器
  • IMP imp:指向方法实现的指针
  • const char *types:表示返回值和参数,例如"v@:"代表"返回值是 void,没有参数";"i@:@"代表"返回值是 int,参数类型为 id"。

对象重定向

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if(aSelector == @selector(mysteriousMethod:)){
        return alternateObject;
    }
    return [super forwardingTargetForSelector:aSelector];
}

消息转发

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([someOtherObject respondsToSelector:
            [anInvocation selector]])
        [anInvocation invokeWithTarget:someOtherObject];
    else
        [super forwardInvocation:anInvocation];
}
  • 在 forwardInvocation: 消息发送前,Runtime 系统会向对象发送methodSignatureForSelector: 消息,并取到返回的方法签名用于生成 NSInvocation 对象,所以我们也需要重写 methodSignatureForSelector: 返回签名。

方法中隐藏的参数

  • 当 objc_msgSend 找到对应方法的实现时,会把消息中的所有参数传给方法的实现,还加上两个隐藏的参数:
    1. self 当前方法的对象指针
    2. SEl 方法选择器

当我们调用[super method]时的过程

  1. 构造 objc_super 结构体 struct objc_super { id receiver; Class super_class; }
    • 其中 receiver 仍然是 self 本身
    • super_class 父类
  2. 因为结构体有 super_class 这个成员变量,系统就会调用 objc_msgSendSuper 这个方法,然后把将这个结构体和方法选择器都传递过去。
  3. 从 objc_super 结构体指向的 superClass 的方法列表开始找 setName 的 selector,找到后再以 objc_super->receiver 去调用这个 selector

即还是 self 去调用父类的方法

推荐一篇关于对象关联的贴子,写得很好
http://www.jianshu.com/p/79479a09a8c0#%E5%85%B3%E8%81%94%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%BA%94%E7%94%A8

相关文章

  • iOS---Runtime

    RunTime runtime 是什么 runtime ,运行时机制,是一套底层 C 语言的 API,其为 iOS...

  • iOS---runtime如何实现weak

    runtime对注册的类会进行布局,对weak对象,runtime会将weak对象添加到一个hash列表中,以we...

网友评论

      本文标题:iOS---Runtime

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