Objective-C学习之Runtime

(以下内容均为本人的理解,不敢保证准确性,如有误请指出,谢谢!)

1.Runtime是什么?

  Runtime是一套组件,Objective-C正因为有了Runtime这套组件,才使得它成为一门完全动态的语言。有了Runtime,我们可以动态决定调用哪个方法(消息传递机制),添加方法,交换方法,给类添加属性,还有字典转模型等。

2.id类型

  id类型可以指向任何一个对象,编译器在编译的时候无法知道该对象属于哪个类,只能到了程序运行的时候才知道具体属于哪个类

3.SEL类型

  SEL是selector在Objective-C中的表示类型。selector可以理解为区别方法的ID。

4.IMP

  IMP是“implementation”的缩写,它是由编译器生成的一个函数指针。当你发起一个消息后,这个函数指针决定了最终执行哪段代码。

5.Method

  Method代表类中的某个方法的类型。

6.Ivar

  Ivar代表类中实例变量的类型

7.objc_property_t

  objc_property_t是属性

8.Cache

  objc_msgSend每调用一次方法后,就会把该方法缓存到cache列表中,下次的时候,就直接优先从cache列表中寻找,如果cache没有,才从methodLists中查找方法。

9.Category

  这个就是我们平时所说的类别了,它可以动态的为已存在的类添加新的方法。

 

一、消息机制

  ①消息传递机制

  在面向对象编程中,对象调用方法叫发送消息。在编译时,程序的源代码就会从对象发送消息转换成Runtime的objc_msgSend函数调用。

  例如:[receiver oneMethod];转化成objc_msgSend(receiver,oneMethod);

  函数objc_msgSend调用过程大概如下:

    (1)检测这个selector是否要忽略。不忽略则下一步。

    (2)检测target是否为nil对象,nil对象接受任何消息都会忽略。target不为nil对象则下一步

    (3)检测对象里是否有实现方法能响应这个消息,如果没有则向父类查找,如果父类没有则继续向上一级查找,直到根类,如果根类都不能响应,则进入消息转发过程。

  ②消息转发机制

  当对象无法正常处理消息时,则进入这个过程:

    (1)调用resolveInstanceMethod:方法决定是否动态添加方法。如果返回NO则进入下一步。

    (2)调用forwardingTargetForSelector:方法,看当前对象是否有内部对象可以响应消息。有则返回内部对象,否则进入下一步。

    (3)这一步将选择子,参数,接收对象封装成一个NSInvocation对象,然后调用forwardInvocation:方法。这时forwardInvocation:方法的实现有两种:一种是修改接收对象,这种实现与第二步返回内部对象类似;另一种实现则是修改消息,例如追加一个参数或修改selector等。如果forwardInvocation:方法没有实现,则进入下一步。

    (4)到了这一步则调用doesNotRecognizeSelector,如果没有实现这个方法,则会crash,整个消息传递和消息转发过程结束。

 

二、Runtime的使用

  要使用Runtime,先包含头文件。如果是模拟器则#import <objc/objc-runtime.h>,如果是真机则

#import <objc/runtime.h>和#import <objc/message.h>,可如下编写: 

    #if TARGET_IPHONE_SIMULATOR

      #import <objc/objc-runtime.h>

    #else

      #import <objc/runtime.h>

      #import <objc/message.h>

     #endif

  Runtime机制提供了很多有用的方法,部分如下:

    Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);  //动态创建一个类

    void objc_disposeClassPair(Class cls);  //销毁一个类

    SEL sel_registerName(const char *str);  //注册一个方法

    void objc_registerClassPair(Class cls);  //注册一个类

    void object_setIvar(id obj, Ivar ivar, id value);  //为对象中的实例变量赋值

    BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types);   //给类添加变量

    BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);  //给类添加方法

    Ivar class_getInstanceVariable(Class cls, const char *name);  //从类中获取一个实例变量

    objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)  //获取类的所有属性

    const char *property_getName(objc_property_t property)  //通过objc_property_t获取属性名称

    Ivar *class_copyIvarList(Class cls, unsigned int *outCount)  //获取类的所有实例变量(包含属性背后的实例变量)

    const char *ivar_getName(Ivar v)              //通过Ivar获取实例变量的名称

    Method *class_copyMethodList(Class cls, unsigned int *outCount)  //获取类的实例方法(不包括类方法和继承的实例方法)

    SEL method_getName(Method m)    //通过Method获取方法SEL(标识)

    const char *sel_getName(SEL sel)  //通过SEL获取方法具体名称

    unsigned int method_getNumberOfArguments(Method m)  //通过Method获取方法参数个数

    

posted @ 2017-03-13 14:20  XuDeHong  阅读(162)  评论(0编辑  收藏  举报