runtime基础、消息转发
来源:互联网 发布:茶叶网络连锁 编辑:程序博客网 时间:2024/06/05 20:29
runtime术语
1、Class、id
#if !OBJC_TYPES_DEFINED/// An opaque type that represents an Objective-C class.typedef struct objc_class *Class;/// Represents an instance of a class.struct objc_object { Class isa OBJC_ISA_AVAILABILITY;};/// A pointer to an instance of a class.typedef struct objc_object *id;#endif
Class是一个指向objc_class结构体的指针;id是一个指向objc_object结构体的指针;而objc_object中的isa指针指向Class结构
2、objc_class
typedef struct objc_class *Class;struct objc_class { Class isa OBJC_ISA_AVAILABILITY; // metaclass#if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; // 父类 const char *name OBJC2_UNAVAILABLE; // 类名 long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0,可以通过runtime函数class_setVersion或者class_getVersion进行修改、读取 long info OBJC2_UNAVAILABLE; // 类信息,供运行时期使用的一些位标识,如CLS_CLASS (0x1L) 表示该类为普通 class,其中包含实例方法和变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法; long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小(包括从父类继承下来的实例变量) struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量地址列表 struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法地址列表,与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储实例方法,如CLS_META (0x2L),则存储类方法; struct objc_cache *cache OBJC2_UNAVAILABLE; // 缓存最近使用的方法地址,用于提升效率; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 存储该类声明遵守的协议的列表#endif}/* Use `Class` instead of `struct objc_class *` */
从以上类objc_class的结构可以看出,类和对象的区别是类比对象多了很多特征成员,类也可以看成objc_object,即分别称作类对象和实例对象。
isa: 实例对象objc_object中的isa指针指向的是类结构objc_class,其中存放着普通成员变量与动态方法(“-”开头的方法);而objc_class中的isa指针指向类对应的元类(metaclass),metaclass中存放着static类型的成员变量与static类型的方法(“+”开头的方法).
3、SEL
SEL是selector在OC中的表示类型,selector可以理解为区别方法的ID
typedef struct objc_selector *SEL;objc_selector的定义如下:struct objc_selector { char *name; OBJC2_UNAVAILABLE;// 名称 char *types; OBJC2_UNAVAILABLE;// 类型};
4、IMP
typedef id (*IMP)(id,SEL,……);
IMP是”implementtation”缩写,它是有编译器生成的一个函数指针。当调用一个消息后,IMP决定了最终执行代码的入口。
5、Method代表类中的某个方法的类型
typedef struct objc_method *Method;struct objc_method { SEL method_name OBJC2_UNAVAILABLE; // 方法名 char *method_types OBJC2_UNAVAILABLE; // 方法类型 IMP method_imp OBJC2_UNAVAILABLE; // 方法实现}
6、Ivar代表类中实例变量的类型
typedef struct objc_ivar *Ivar;struct objc_ivar { char *ivar_name OBJC2_UNAVAILABLE; // 变量名 char *ivar_type OBJC2_UNAVAILABLE; // 变量类型 int ivar_offset OBJC2_UNAVAILABLE; // 基地址偏移字节#ifdef __LP64__ int space OBJC2_UNAVAILABLE; // 占用空间#endif}
7、objc_property_t属性
typedef struct objc_property *objc_property_t;
objc_property是内置的类型,与之关联的还有一个objc_property_attribute_t,它是属性的attribute,也就是其实是对属性的详细描述,包括属性名称、属性编码类型、原子类型/非原子类型等。它的定义如下:
typedef struct { const char *name; // 名称 const char *value; // 值(通常是空的)} objc_property_attribute_t;
8、Catagory
这个就是我们平时所说的类别了,很熟悉吧。它可以动态的为已存在的类添加新的方法。
它的定义如下:
typedef struct objc_category *Category;struct objc_category { char *category_name OBJC2_UNAVAILABLE; // 类别名称 char *class_name OBJC2_UNAVAILABLE; // 类名 struct objc_method_list *instance_methods OBJC2_UNAVAILABLE; // 实例方法列表 struct objc_method_list *class_methods OBJC2_UNAVAILABLE; // 类方法列表 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议列表}
常见方法
1、获取属性的列表—-class_copyPropertyList()
objc_property_t *propertyList = class_copyPropetyList([self class],&count);
2、获取方法列表-class_copyMethodList()
Method *methodList = class_copyMethodList([self class],&count);
3、获取成员变量列表-class_copyIvarList()
Ivar *ivarList = class_copyIvarList([self class],&count);
4、获取协议列表-class_copyProtocolList
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class],&count);
5、获取方法-objc_getClass
现有一个Person类,和person创建的xiaoming对象,有test1和test2两个方法
获得类方法Class PersonClass = object_getClass([Person class]);SEL oriSEL = @selector(test1);Method oriMethod = class_getInstanceMethod(xiaomingClass, oriSEL);获得实例方法Class PersonClass = object_getClass([xiaoming class]);SEL oriSEL = @selector(test2);Method cusMethod = class_getInstanceMethod(xiaomingClass, oriSEL);
6、添加方法
BOOL adduce = class_addMethod(xiaomingClass,oriSEL,method_getImplementation(cusMethod),method_getTypeEncoding(cusMethod));
7、替换原方法实现
class_replaceMethod(toolClass,cusSel,Method_getImplementation(oriMethod),method_getTypeEncoding(oriMethod));
8、交换两个方法
method_exchangeImplementation(oriMethod,cusMethod);
常见作用
动态添加对象的成员变量和方法
动态交换两个方法的实现
拦截并替换方法
在方法上增加额外的功能
实现NSCoding的自动归档和解档
实现字典转模型的自动转换
runtime的消息传递
(1)发送消息涉及的函数
在OC程序中向一个对象发送消息,编译时会转换成runtime的objc_msgSend函数的调用,
例如某实例变量receiver实现oneMethod的函数调用
[receiver oneMethod];
会转换成类似一下的代码
objc_msgSend[receiver,selector];
实际上Runtime会根据类型自动转换成下列的某一函数
objc_msgSend:普通的消息都会通过该函数发送
objc_msgSend_stret:消息中有返回值(不是简单值)时,通过该函数发送消息,并接受返回值
objc_msgSendSuper:和objc_msgSend类似,把消息发送给父类的实例
objc_msgSendSuper_stret和objc_msgSend_stret类似:消息发型给父类的实例并接受返回值
(2)objc_msgSend函数的调用过程
第一:检查这个selector是不是要忽略的
第二:检查这个target是不是nil对象,nil对象发送的任意消息都会被忽略
第三:当调用实例方法时,它会根据自身的isa指针指向的类(class)的methodLists中查找该方法,如果找不到则会通过class的super_class指针找到父类,进而在父类中methodLists中查找该方法,如果还是找不到,则继续通过父类的super_class指针找到父类的父类,直到根类
当调用类方法时,它会通过自己的isa指针找到metaclass,并在metaclass中的methodLists中查找该方法,如果找不到则会通过metaclass中的super_calss指针找到其父类,然后在父类的methodLists中查找该方法,如果还是找不到,则继续通过父类的super_class指针找到父类的父类,直到根类metaclass
第四:如果第三步还是找不到就会进入动态方法解析
*通过resolveInstanceMethod:方法决定是否动态添加方法。如果返回YES,则通过class_addMethod动态添加方法,使消息得到处理;如果返回NO,则进入下一步。
*这一步进入forwordingTargetForSelector:方法,用于指定备选对象来响应这个selector(不能指定self),如果返回某个对象则会调用该对象的方法,结束;如果返回nil,则进入下一步
*这一步会调用methodSignatureForSelector:方法签名,如果返回nil,则消息无法处理;如果返回methodSignature,则调用forwordInvocation:方法,我们可以通过anInvocation对象修改实现方法、修改响应对象等,如果调用成功,则结束。如果失败,进入doseNotRecognizeSelector方法,如果没有实现该方法,就会crash
学习时的Demo:https://github.com/onebutterflyW/runtime
参考网址:https://www.ianisme.com/ios/2019.html
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/#SEL
- runtime基础、消息转发
- Runtime之消息转发
- iOS runtime 消息转发
- Runtime消息转发机制
- Runtime消息转发机制
- Runtime系列(消息转发)
- iOS runtime 之消息转发
- runTime 的消息转发机制
- runtime浅谈(三)消息转发
- runtime选择器和消息转发处理
- iOS runtime学习之消息转发机制
- ios runtime IMP指针 消息转发机制
- runtime(三)应用 消息转发
- iOS Runtime与消息转发机制
- 为所欲为之API兼容-Runtime消息转发
- OC学习Runtime之消息传递,消息转发机制
- Objective-C runtime之消息转发机制(三)
- Objective-C runtime之消息转发机制(三)
- 面向对象的程序设计Java-基本数据类型
- 食物链
- AI学习之路(9): 张量的常量1
- 走迷宫dfs
- Count the Sheep
- runtime基础、消息转发
- java安全架构____DES加密原理
- spring-aop注解配置
- Linux和windows环境下的Java开发的区别与不同
- dalvik机器码对照表
- BeautifulSoup 安装
- PAT甲级练习1053. Path of Equal Weight (30)
- use generator and co in mocha
- nfs部署和优化