1. 对象的本质:
数据结构:
objc_object
id(对象)=objc_object
1. isa_t(共用体)
2. 关于isa操作的方法
3. 弱引用相关
4. 关联对象相关
5. 内存管理相关
objc_class
Class=objc_class(类也是对象)->继承自objc_object
1. Class superClass(类对象指向的是父类对象)
2. cache_t cache(方法缓存结构)
3. class_data_bits_t bits(关于类定义的变量方法都在此结构中)
isa指针
共用体isa_t
32或64位01数字,分为指针型的isa(isa的值代表的是Class的地址).非指针型isa(isa的值的部分代表的是Class的地址).
isa指向
1. 实例对象指向类对象.(实例->Class)
2. 类对象指向其元类对象.(Class->meteClass)
cache_t
用于快速查找方法执行函数.
可增量扩展的哈希表结构
结构类似数组
bucket_t结构数组包含(key IMP)
key:
IMP:无类型的函数指针
class_data_bits_t
是对class_rw_t的封装,类的读写信息,分类的方法属性协议.
代表了类相关读写信息,对class_ro_t的封装(read-only).
class_ro_t代表类的相关只读信息.
class_rw_t
1. class_ro_t.
2. protocols分类中信息.结构是list_array_tt (二维数组)
3. properties分类中信息.结构是list_array_tt(二维数组)
4. methods分类中信息.结构是list_array_tt (二维数组)
class_ro_t
1. name(类名)
2. ivars(成员变量) (一维数组)
3. properties (一维数组)
4. protocols (一维数组)
5. methodList (一维数组各元素为method_t)
与上面的区别上面储存的是分类中的内容,因为分类有多个所以是二维数组储存.下面是原理定义类的内容.
method_t结构体.是将函数四要素封装抽象
1. SEL name;(方法名称)
2. const char* types(包含函数返回值和参数组合)
3. IMP imp(无类型的函数指针对应函数体)
types结构:Type Encodings技术
返回值,参数1,参数2...参数n.(例如 -(void)aMethod对应runtime结构就是v@: v对应返回值void,@对应第一个参数必须是id类型的消息的接收者,:代表SEL代表固定的第二个参数)
整体的数据结构.上面就可以分析了
2. 对象,类对象和元类对象.
类对象:存储实例方法列表等信息
元类对象:储存类方法列表等信息
根类指向nil.对应的是NSObject,
所有元类对象的isa指针都直接指向根元类对象,含括他自己.根元类对象的superClass指针指向更类对象.
思考:
如果我们调用类方法,没有对应的实现,但是有同名的实例方法实现?会怎么样?为啥?
因为根元类对象的superClass指针指向根类对象,当没有查找到类方法的实现的时候,系统会查找根类中实例方法的实现调用所以不会发生崩溃.
3. 消息传递的机制:
调用的实例方法A.系统会根据当前实例的isa指针找到当前实例的类对象查找实例有实例方法的实现,如果没有会根据superClass的指向逐级查找父类的实例方法.如果最后没有查找到就会走到消息转发流程.类方法类似,只是查找元类对象
首先调用一个方法->缓存方法是否命中->没有命中,根据isa指针找到当前类查找实例方法->没有命中,逐级父类方法查找->消息转发流程.
1. 缓存查找: 在cache_t通过哈希查找(通过给定的值,经过哈希算法找到给定值对应的数组中的索引位置),找到bucket_t从而找到对应方法的IMP实现.
2. 当前类中的查找: 1. 对于已排序好的方法,采用二分法查找.2. 对于未排序好的方法采用一般查找.
3. 父类逐级查找: 通过superClass指针访问父类,判断父类是否为空(是否是NSObject).不为空逐级向上查找.
整体过程,每个查找的具体过程.
4. 消息转发机制:
resolveInstanceMethod:
forwardingTargerForSelector:
methodSignatureForSelector:
forwardInvocation:
实例方法:resolveInstanceMethod:
返回值时BOOL类型的.
参数是SEL.
类方法.
如果返回值时YES或者实现了resolveInstanceMethod相当于告诉系统方法已处理.返回NO会回调forwardingTargerForSelector:
forwardingTargerForSelector:
返回值时id
参数是SEL.
如果指定转发目标,系统会把消息传递给转发目标.返回nil会调用methodSignatureForSelector:返回方法签名调用forwardInvocation.消息无法处理
类方法:resolveClassMethod:
method-swizzing:方法交换,修改对应方法的方法实现.
实际使用:添加统计信息.添加报错信息
为一个类动态添加方法:performSelector
可以在消息的转发中动态添加方法的实现:class_addMethod()动态添加.
动态方法解析?@dynamic申明属性在实现中标示成@dynamic,不需要编译器在编译时生成get,和set方法的具体实现,而是get,和set方法我们调用时是在运行时添加.
#import <Foundation/Foundation.h>
@interface Man : NSObject
@property (nonatomic,strong)NSString *name;
@property (nonatomic,strong)NSString *sex;
@end
// Man.m
#import "Man.h"
@implementation Man
@dynamic name, sex;
@end
动态运行时语言将函数决议推迟到运行时.编译时语言在编译期进行函数决议.
网友评论