本文翻译自苹果官方文档,原文在此,个人能力有限,有翻译不准确的地方,希望各位读者在评论区多多评论,我会对本文不断进行更新完善。
本章讲述如何动态地提供一个方法的实现。
1 动态方法解析
有些情况下,你可能想要动态地提供方法的实现。例如,Objective-C声明属性特征(see Declared Properties inThe Objective-C Programming Language)包括@dynamic指令:
@dynamic propertyName;
它告诉编译器,与该属性相关联的方法将动态地提供。
你可以实现resolveInstanceMethod:和resolveClassMethod: 方法来动态地分别为一个给定的实例或类方法的选择器提供一个实现方法。
一个OC方法就是一个至少有有两个参数--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。
2 动态加载
OC程序可以在运行过程中加载和链接新的类和类别。新代码合并到程序中,并与一开始加载的类和类别进行相同的处理。
动态加载可以用来所很多不同的事情。比如,系统偏好设置程序中的各个模块是动态加载的。
在Cocoa环境中,通常使用动态加载允许应用程序能够被定制。别人可以写一个模块供你的应用程序在运行时调用--就像Interface Builder加载自定义调色板和OS X系统偏好设置加载自定义偏好模块一样。可加载模块扩展了程序的功能。他们按照你允许的方式发挥作用,但不能按照自己的期望预先定义。你提供框架,别人提供代码。
虽然Mach-O文件(objc_loadModules, defined inobjc/objc-load.h)中存在一个执行动态加载OC模块的函数,但更重要的是Cocoa框架的NSBundle类为动态加载提供了一个更加方便的接口,该类是面向对象的,并且集成了多种服务。查看Foundation框架参考书中的NSBundle类说明书,以获得NSBundle类及其相关的使用信息。查看OS X ABI Mach-O文件格式参考书获得Mach-O文件的信息。