Objective-C是一门面向运行时的语言,它尽可能的把一些编译和链接时需要执行的逻辑延迟到运行时,使Runtime可以按需要把消息重定向到合适的对象,以实现动态添加属性和动态方法交换等等。
Objective-C在编译阶段并不会去绑定执行的函数,只有在运行的时候才会到类和对象的方法列表中查找对应的方法。
OC中的方法查找
OC在进行消息传递的时候,会先到缓存中以哈希查找的方式去查找缓存,若缓存命中,则执行对应方法。若未命中,则从当前类的方法列表中取查找。
从当前类的方法列表中查找(对于已完成排序的列表,采用二分查找法去查找对应的方法实现。对于没有完成排序的算法,采用一般遍历查找法去查找对应方法的实现),若在当前类方法列表中命中,则执行,否则再到父类方法列表中去查找,以重复这一过程。
OC中的消息传递
Objective-C中的消息发送是通过objc_msgSend(id, SEL,...)来实现的。Objective-C中的消息传递就是一次方法查找的过程。Objective-C调用一个方法,先去当前类中查找该方法的imp,如果查找不到,则到父类中能够去查找...以此类推,如果到根类中没有查找到该方法,则此次方法传递结束。
OC中的消息转发
Objective-C中消息转发过程如下所示:
- 先调用resolveInstanceMethod,如果在这里使用runtime动态添加对应的方法,并且返回YES,消息就找到了响应的对象,并将这个新增的方法添加到类的方法缓存列表
- 如果上面的方法返回NO的话,对象会调用forwardingTargetForSelector方法,以实现消息的转发,让其他对象来处理这个消息。
- 如果以上两个方法都没有做处理,那么对象会执行最后一个方法methodSignatureForSelector,提供一个有效的方法签名。若提供了有效的方法签名,程序会通过forwardInvocation方法执行签名。若没有提供方法签名,触发doesNotRecognizeSelector方法,触发崩溃。
resolveInstanceMethod
resolveInstanceMethod是Objective-C语言中一种动态方法解析的接口,是得我们可以在运行时动态的为一个selector提供实现。我们只需要实现 +resolveInstanceMethod和+resolveClassMethod方法,并在其中为指定的selector提供实现即可(通过调用运行时函数class_addMethod来添加)。这两个方法都是NSObject中的类方法,其原型为:
+ (BOOL)resolveClassMethod:(SEL)name;
+ (BOOL)resolveInstanceMethod:(SEL)name;
参数那么是需要被动态解析的selector;如果在该函数中为指定的selector提供实现,无论返回YES还是NO,编译运行都是正确的。如果在该函数内并没有真正的为selector提供实现,如果返回YES,运行会crash。其原理很简单,因为当前类既没有为selector提供实现,又没有实现消息转发,自然会crash。
forwardingTargetForSelector
forwardingTargetForSelector是Objective-C语言中消息快速重定向的函数。开发者可以在派生类中对其进行重载,从而将无法处理的selector转发给另一个对象。
methodSignatureForSelector
methodSigntureForSelector的作用在在于为另一个类实现的消息创建一个有效的方法签名。如果没有实现有效的方法签名,程序就会崩溃
forwardInvocation
在返回有效的方法签名的情况下,当前对象则会调用forwardInvocation方法,以完成消息的最终传递。