Objective-C Runtime编程指南之动态方法解析
动态方法解析
本章节描述了如何动态地为方法提供实现。
动态方法解析
有一些情况下,你可能想要为方法动态地提供实现。比如,声明的Objective-C属性的特性(在The Objective-C Programming Language中查看Declared Properties)中包含了 @dynamic 关键字:
@dynamic propertyName;
它告诉了编译器与属性相关的方法需要动态提供。
你分别可以通过实现resolveInstanceMethod:和resolveClassMethod:方法为指定的实例方法或类方法的选择器动态地提供实现。
一个Objective-C方法就是一个至少包含了两个参数的C函数----self 和 _cmd 。你可以通过使用class_addMethod函数给类添加一个函数。因此,给定了如下函数:
void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
像下面这样,你可以使用resolveInstanceMethod: 方法来给类动态添加一个方法:
@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(resolveThisMethodDynamically)) {
class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:aSEL];
}
@end
转发方法(在Message Forwarding中描述的那样)和动态方法解析是在对立面的。一个类在转发机制进入之前,有机会动态解析出一个方法。如果respondsToSelector:或instancesRespondToSelector:被调用,动态方法解析器就会首先给机会让选择器提供一个IMP。如果你实现了resolveInstanceMethod:方法,但是想要指定选择器通过转发机制转发走,你可以在那些选择器中返回NO。
动态加载
一个Objective-C程序可以在运行的过程中加载和链接新的类和分类。新的代码被添加到程序中并且与在程序开始时加载的类和分类同等对待。
动态加载可以被用于做许多不同的事情。比如,在系统偏好设置程序中,各种模块都是动态加载的。
在Cocoa环境中,动态加载普遍用于允许程序的自定义上。第三方可以编写一些在运行时加载的模块----就像Interface Builder加载自定义调色板或者是OS X系统偏好设置加载自定义设置模块一样。可加载的模块扩展了应用程序的功能。这个功能可以在你允许但是可能没有想到的方式上给应用程序提供帮助。你提供了框架,第三方可以提供代码。
虽然在Mach-O文件中,有一个运行时函数可以执行Objective-C模块的动态加载(objc_loadModules,定义在objc/objc-load.h文件中),Cocoa的NSBundle类提供了一个更加方便的接口用于动态加载----一个面向对象的并且与相关服务结合到一起的接口。在Foundation框架参考中查看NSBundle类的相关说明及使用方法。在OS X的ABI Mach-O文件格式参考中查看Mach-O文件的相关信息。