Class 数据结构:
getIsa( ) 为获取 isa 指向的类,isa 指向的类是对象的真实类型。
objc_object 结构体包含一个 isa 指针,类型为 isa_t 联合体。 可表示多种形态,既可以当成是指针,也可以存储标志位。
注意: isa 指针不总是指向实例对象所属的类,不能依靠它来确定类型,而是应该用 class 方法来确定实例对象的类。因为KVO的实现机理就是将被观察对象的 isa 指针指向一个中间类而不是真实的类,这是一种叫做isa-swizzling的技术。
1. Class是一个指向objc_class(类)结构体的指针,而id是一个指向objc_object(对象)结构体的指针。
2. 类结构体 (objc_class)继承自对象结构体(objc_object),所以类也是对象。isa指针,也是从object结构体继承来的isa。
isa 指向总结:
1. 对象 (objec_object )的isa指针, 指向他的类对象。
2. 类对象 (objec_class)的isa 指针, 指向他的元类。
注⚠️:类对象中存放着普通成员变量与对象方法 (“-”开头的方法),类对象 在编译期产生用于创建实例对象,是单例。
注⚠️:成员变量是存放在类对象中的,并且编译的那一刻就已经决定好了。而分类是在运行时才去加载的。 分类的结构中没有成员变量列表,因此分类中不可以添加成员变量。
3. 元类(metaclass):也是一个对象,所有的元类的 isa 指针都会指向一个根元类。元类中保存了创建类对象以及类方法所需的所有信息(+ 方法列表 )。
4. 根元类的isa指针又会指向他自己,形成一个闭环。根元类 super class父类指向NSObject类对象。
5. 每个类仅有一个类对象,而每个类对象仅有一个与之相关的元类。
6. super_class 指针指向 objc_class 类所继承的父类,如果当前类已经是最顶层的类(如NSProxy), 则 super_class 指针为 NULL。
对象方法的调用: 在运行时编译器会将代码转化为 objc_msgSend(obj, @selector (selector))
1. 首先通过obj(对象)的 isa 指针找到obj(对象)对应的class(类)
2. 在class(类)中先去cache 中通过SEL(方法的编号)查找对应method(方法)
3. 若cache中未找到,再去methodLists中查找
4. 若methodists中未找到,通过 super_class向上一级父类结构体中查找,直至根class(也就是NSObject), 找到后 将method(方法)加入到cache中,以方便下次查找
5. 找到后通过method(方法)中的函数指针 IMP 跳转到对应的函数中去执行。
类方法的调用:
1. 通过自己的 isa 指针指向的 objc_class 中的 isa 指针找到元类
2. 从元类的 methodLists 中查找该类方法,找不到则会通过元类 的super_class指针找到父类的元类结构体,然后从methodLists中查找该方法,如果仍然找不到,则继续通过super_class向上一级父类结构体中查 找,直至根元类
3. 找到后通过method(方法)中的函数指针 IMP 跳转到对应的函数中去执行。
objc_cache: 方法缓存列表
找到要执行的方法后,把方法 的 method_name 作为key ,method_imp作为value 给存起来。当再次收到这个消息的时候,可以直接在cache 里找到,避免去遍 objc_method_list。提高效率。
method_imp: 指向实现程序的内存地址的指针。
注意:
如果直到 根类还是无法找到对应的方法,说明该接收者对象响应该消息,那么就会触发消息转发机制,给开发者最后一次挽救程序crash的机会。如果消息转发都失败了就回执行doesNotRecognizeSelector:方法报unrecognized selector错。
iSA 日常使用 --- kvo的实现原理:
1. 系统动态的生成一个类对象,这个类是监听对象的类的子类
2. 在生成的子类中重写了被监听的属性的set方法,之后将监听对象的isa指针指向系统动态生成的这个类
3. 当监听对象调用set方法时,由于监听对象的isa指针指向的是刚刚动态生成的类,所以执行的set方法也是子类中重写的set方法。
参考:kvo原理传送门
实现类似于多继承:通过rutime 修改某个对象isa指针的指向,让对象调用一些原本不属于他的方法。(消息转发)isa--swizzing
OC的函数,属于动态调用过程,在编译期并不能决定真正调用哪个函数,只有在真正运行时才会根据函数的名称找到对应的函数来调用。因此给一个对象发送消息,并不会立即执行。
Objective-C的优点是它是动态的。动态能力有三种:
动态类-运行时确定类的对象
动态绑定-运行时确定要调用的方法
动态加载--运行时为程序加载新的模块:添加分类,方法,属性等。
参考:
苹果开发中文网站 - OC-底层实现isa指针 - CocoaChina_让移动开发更简单
isa指针介绍 - ,变成一个共用体(union)结构,用位域来存储更多的信息