笔者翻译自iOS Developer Library Dynamic Method Resolution
动态方法解决方案
这章解释了如何动态地提供一个方法的实现。
动态方法解决方案
有时候,你可能想动态地提供一个方法的实现。例如:Object-C 声明属性特性(参考 Object-C 编程语言中声明属性) 时包含了 @dynamic
指令:
@dynamic propertyName;
这样就告诉编译器与该属性相对应的方法将被动态提供。
你能实现 resolveInstanceMethod:
和 resolveClassMethod:
函数分别为实例方法和类方法提供动态方法实现。
Object-C 方法仅仅是一个至少带有两个参数(self 和 _cmd)的C函数。你能使用 class_addMethod
给类添加一个函数作为类中的方法。
void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
你能使用 resolveInstanceMethod:
动态地将它添加到一个类作为类的实例方法(方法名为:resolveThisMethodDynamically),如下所示:
@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:
被调用,动态方法解决器将优先给函数选择器提供机会使它能绑定一个方法实现。如果你实现了 resolveInstanceMethod:
,但希望指定的选择器被转发机制转发,你应该为这些选择器返回 NO。
动态加载
Object-C 程序能在运行时加载和链接新的类和分类。新的代码将整合到程序中,并且与程序一开始加载的类和分类同等对待。
动态加载能被用作许多不同的情况。例如:在系统偏好应用中种类繁多的模块被动态加载。
在 Cocoa 环境中,动态加载通常被用作能被自定义定制的应用。其他人可以编写能在你的程序运行时加载的模块——就像 Interface Builder 加载用户调色板和 OS X 系统偏好设置应用加载用户偏好模块。这些可加载的模块扩展了你的应用功能。它们通过你允许但是你不能预测和自定义的方式实现。你提供了框架,但其他人提供代码。
尽管在 Mach-O 文件(objc_loadModules, 在 objc/objc-load.h 中定义)中,有能够动态加载 Object-C 模块的运行时函数, Cocoa NSBundle
类提供了更方便的动态加载接口——它是面向对象的且集成了很多相关的服务。在 Foundation 框架说明中参考 NSBundle
类的特性并获取更多 NSBundle
类的信息及如何使用它。参考 Mach-O 文件的 OS X ABI Mach-O File Format Reference 获取更多信息。