本章描述了如何动态的提供一个方法的实现。
动态方法解析
在有些情况下,需要动态的提供一个方法的实现。例如,Objective-C 声明的属性特征(见Objective-C 编程语言中的声明属性)包含@dynamic指令:
<pre><code>@dynamic propertyName; </pre></code>
它告诉编译器,将动态的提供该方法与属性。
可以实现resolveInstanceMethod: 和resolveClassMethod: 方法来动态的提供一个给定选择器的实例和对应的类方法提供实现。
一个Objective-C 方法仅仅是一个至少有两个参数self和_cmd的C函数。可以添加在类中添加一个函数作为一个使用class_addMethod.函数的方法。因此,有以下函数:
<pre><code>
void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
</pre></code>
可以动态的将它添加到类中作为一个使用 resolveInstanceMethod: 的方法(称为resolveThisMethodDynamically):
<pre><code>
@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
</pre></code>
转发方法(消息转发)和动态方法解析很大程度上是正交的。一个类有机会在转发机制开始工作前动态解析方法。如果调用respondsToSelector: 或instancesRespondToSelector:,动态方法解析器会为选择器提供IMP。如果实现resolveInstanceMethod: ,但实际上想通过转发机制来转发特定的选择器,将返回NO。
动态加载
一个Objective-C程序可以在运行过程中加载和链接新类和分类。程序中纳入新代码,在开始加载的类和类别中都可以使用。
动态加载可以用来做很多不同的事情。例如,系统偏好设置应用程序中的模块都是动态加载的。
在Cocoa 环境中,动态加载通常用来自定义应用程序。其他人可以编写模块让你的程序在运行时加载,类似IB加载自定义调色板和OS X系统设置应用程序加载自定义偏好模块。可加载模块可扩展应用程序。他们以你允许的方式贡献代码,但是不能自己预计和定义。你提供框架,其他人提供代码。
尽管有一个运行时函数在Mach-O 文件(在objc/objc-load.h中定义的objc_loadModules)中,执行 Objective-C 模块的动态加载。Cocoa的NSBundle 类为动态加载提供了更方便的接口,这个接口是面向对象并与相关服务结合。了解NSBundle 类信息和使用,可参阅基础框架引用中的NSBundle 类规范。Mach-O 文件信息可查看OS X ABI Mach-O文件格式引用。
网友评论