Dynamic Method Resolution
This chapter describes how you can provide an implementation of a method dynamically.
Dynamic Method Resolution
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 Propertiesin The Objective-C Programming Language) includes the @dynamic
directive:
@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.
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:
void dynamicMethodIMP(id self, SEL _cmd) { |
// implementation .... |
} |
void dynamicMethodIMP(id self, SEL _cmd) { |
// implementation .... |
} |
you can dynamically add it to a class as a method (called resolveThisMethodDynamically
) using resolveInstanceMethod:
like this:
@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 |
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 return NO
for those selectors.
你可以动态的添加到一个类 作为一个方法 (叫做 resolveThisMethodDynamically)使用 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 |
转发方法(如消息转发机智)和动态解析的方法是 主要的,相互垂直的?一个类有机会去动态的解决一个方法在它转发机制开始生效之前。如果respondsToSelector:或者 instancesRespondToSelector: 被调用,这个动态方法解析有机会去首先提供一个IMP机制给选择器。如果你实现 resoveInstanceMethod: 但是想要特别的选择器去通过转发机制转发,那么你就对这些选择器返回NO。
Dynamic Loading
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.
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 in objc/objc-load.h
), Cocoa’s NSBundle
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 the NSBundle
class and its use. See OS X ABI Mach-O File Format Reference for information on Mach-O files.