4.Runtime官方文档学习--动态方法解析
1.动态方法解析
There are situations where you might want to provide an implementation of a method dynamically. For example, the Objective-C declared properties feature (see Declared Properties in The Objective-C Programming Language) includes the
@dynamic
directive:
在很多情况下,你可能想要动态地提供一个方法的实现。例如,Objective-C声明属性的功能(参见The Objective-C Programming Language的 Declared Properties)包含了@dynamic
指令。
@dynamic propertyName;
which tells the compiler that the methods associated with the property will be provided dynamically.
它告诉编译器和属性相关联的方法会被动态提供。
You can implement the methods resolveInstanceMethod: and resolveClassMethod: to dynamically provide an implementation for a given selector for an instance and class method respectively.
你可以实现方法resolveInstanceMethod: and resolveClassMethod: 来分别为实例方法和类方法动态提供给定选择器的实现。
An Objective-C method is simply a C function that take at least two arguments—
self
and_cmd
. You can add a function to a class as a method using the function class_addMethod. Therefore, given the following function:
Objective-C方法只是一个至少有两个参数--self
and _cmd
--的C函数。你可以使用函数 class_addMethod为类添加一个函数作为方法。因此,给出以下函数:
void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
you can dynamically add it to a class as a method (called
resolveThisMethodDynamically
) usingresolveInstanceMethod:
like this:
你可以使用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
这个例子是指调用一个只有声明的方法resolveThisMethodDynamically
,为其动态添加实现,也就是将dynamicMethodIMP
作为它的实现。
Forwarding methods (as described in Message Forwarding) and dynamic method resolution are, largely, orthogonal. A class has the opportunity to dynamically resolve a method before the forwarding mechanism kicks in. If respondsToSelector: or instancesRespondToSelector: is invoked, the dynamic method resolver is given the opportunity to provide an
IMP
for the selector first. If you implement resolveInstanceMethod: but want particular selectors to actually be forwarded via the forwarding mechanism, you returnNO
for those selectors.
转发消息(如 消息转发中所述)和动态方法解析在很大程度上是正交的(orthogonal)。类有机会在转发机制启动之前动态解析方法。如果调用了 respondsToSelector: 或 instancesRespondToSelector:,动态方法解析器有机会首先为选择器提供IMP
。如果你实现了resolveInstanceMethod:但希望通过转发机制实际去转发特定的选择器,则为这些选择器返回NO
。
也就是说如果想自己手动为方法动态添加实现,就实现resolveInstanceMethod:方法并在其中添加IMP
,如果实现了这个方法但是却不想手动添加方法实现,而是希望转发机制去转发消息,就在这个方法中返回NO
。
2.动态加载
An Objective-C program can load and link new classes and categories while it’s running. The new code is incorporated into the program and treated identically to classes and categories loaded at the start.
Objective-C程序在运行的时候可以加载和链接新的类和类别。新的代码会被合并到程序中,并且与开始加载的类和类别相同(运行时加载的类和类别同程序开始加载时的类和类别没有区别)。
Dynamic loading can be used to do a lot of different things. For example, the various modules in the System Preferences application are dynamically loaded.
动态加载可以被用来做很多不同的事情。例如,在系统偏好程序中的很多模块都是动态加载的。
In the Cocoa environment, dynamic loading is commonly used to allow applications to be customized. Others can write modules that your program loads at runtime—much as
Interface Builder
loads custom palettes and the OS X System Preferences application loads custom preference modules. The loadable modules extend what your application can do. They contribute to it in ways that you permit but could not have anticipated or defined yourself. You provide the framework, but others provide the code.
在Cocoa环境中,动态加载通常被用于允许自定义应用程序。其他人可以编写你的程序在运行时加载的模块,就像Interface Builder
加载自定义调色板和OS X系统偏好程序加载自定义偏好模块。可加载模块扩展了应用程序的功能。它们以你允许的方式做出贡献,但是无法预测或定义你自己。你提供框架,其他人提供代码。
Although there is a runtime function that performs dynamic loading of Objective-C modules in Mach-O files (
objc_loadModules
, defined inobjc/objc-load.h
), Cocoa’sNSBundle
class provides a significantly more convenient interface for dynamic loading—one that’s object-oriented and integrated with related services. See the NSBundle class specification in the Foundation framework reference for information on theNSBundle
class and its use. See OS X ABI Mach-O File Format Reference for information on Mach-O files.
虽然有一个运行时函数可以在Mach-O文件中执行Objective-C模块的动态加载,但是Cocoa的NSBundle
类为动态加载提供了一个非常方便的接口--面向对象并且继承了相关服务。有关NSBundle
类及其用法的信息,请参考Foundation框架指南中的 NSBundle 类规范。有关Mach-O文件的信息,请参阅OS X ABI Mach-O文件格式指南。