一年多的iOS开发经验,也学习了一些有关Runtime的知识,在这里写下自己的一点小心德。
学习runtime个人认为主要理解两点:1.类(对象)的底层实现 2.OC的消息机制
runtime是C语言写的,OC中的类在runtime中都转变成结构体表示。
在OC中NSObject为基类,找到NSObject.h文件中NSObject的定义:
@interface NSObject {
Class isa OBJC_ISA_AVAILABILITY;
}
我们可以看到基类中有一个名为isa的成员变量,isa其实是一个指向objc_class的结构体指针。按住Command键,点击进入,来到objc_class的定义(同时你会发现来到runtime.h中):
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;
当我们创建obj时,每个obj中都有一个isa指针,指向自己的类的结构体。接下来讲解下这个结构体主要的成员:
1.isa指针:obj中的isa指向类的结构体,而类的结构体中的isa又指向谁呢?其实isa指向元类metaclass。
2.super_class指针:指向类的父类。(下面盗用一张图帮助理解,继承之间两种指针的指向)

3.ivars:类的成员变量列表指针,用于存放类的成员变量。
4.methodLists:类的方法列表指针,用于存放类的方法列表。
PS:这里同学们自己在runtime.h中搜索下这几个结构体的构成,理解了会有大帮助。
类的其他成员就不一一列举了。
第2点:OC的消息机制。
在开始前,同学们应该先了解SEL、IMP、Method三者间的关系。
当obj或者class调用一个方法时(相当于往obj或class发送一个SEL),会先找到isa指针指向的metaClass,然后在metaClass中找到methodLists,从methodLists中根据SEL找到相应的IMP,并执行IMP。如果找不到,则从superClass中找,直到rootClass中还找不到相应的IMP,则系统会进行以下三个步骤:
1.如果一直找不到IMP,调用+ (BOOL)resolveInstanceMethod:方法,返回NO告诉系统找不到IMP。
2.调用- (id)forwardingTargetForSelector:方法返回一个对象,将消息转发到该对象(默认应该是返回nil对象)。
3.如果转发对象中也找不SEL相应的IMP,系统会调用- (NSMethodSignature *)methodSignatureForSelector:方法返回一个NSMethodSignature对象(默认应该为nil),系统根据NSMethodSignature对象,创建一个NSInvocation对象,然后调用- (void)forwardInvocation:方法(forwardInvocation默认调用- (void)doesNotRecognizeSelector:抛出异常)。
了解到OC的消息机制后,说说我们可以在这个机制中做什么?
1.在调用+ (BOOL)resolveInstanceMethod:时,可以这里动态地为SEL往Method中添加IMP,并返回YES,可以防止程序的崩溃。
2.在调用- (id)forwardingTargetForSelector:时可以返回一个拥有SEL对应的IMP的obj,这样使原来的obj在没有继承拥有该IMP类的情况下可以使用该SEL,变相地使OC有多继承的效果。
3.重写- (NSMethodSignature *)methodSignatureForSelector:和- (void)forwardInvocation:方法,重SEL转发给一个拥有相应IMP的obj。
以上三种做法,可以在参考中找到具体实现。其中1的原理是动态添加IMP,2和3原理都是把消息转发到一个有相应IMP的obj。
到这里,同学们对OC的底层实现,runtime应该有一个更好的了解了。相信了解了构造后,再来理解功能就变得简单些啦。
打开runtime.h文件,点击selection列表,我们可以总体的浏览下runtime的方法和定义,定义呢主要就是我们上面讲的底层实现结构,而这里的方法主要有object、objc、class、ivar、sel、imp和method这些开头。从方法名开头可以看出,主要是对对象、类、属性、方法选择器、方法实现和方法的操作。
以上是我学习runtime的方法和一些小心得,希望对同学们有帮助。
最后,希望大家指点出不足与错误之处。
网友评论