本章描述了如何動態(tài)的提供一個方法的實現(xiàn)巷燥。
動態(tài)方法解析
在有些情況下倔撞,需要動態(tài)的提供一個方法的實現(xiàn)寸士。例如渤愁,Objective-C 聲明的屬性特征(見Objective-C 編程語言中的聲明屬性)包含@dynamic指令:
<pre><code>@dynamic propertyName; </pre></code>
它告訴編譯器牵祟,將動態(tài)的提供該方法與屬性。
可以實現(xiàn)resolveInstanceMethod: 和resolveClassMethod: 方法來動態(tài)的提供一個給定選擇器的實例和對應的類方法提供實現(xiàn)抖格。
一個Objective-C 方法僅僅是一個至少有兩個參數(shù)self和_cmd的C函數(shù)诺苹。可以添加在類中添加一個函數(shù)作為一個使用class_addMethod.函數(shù)的方法雹拄。因此收奔,有以下函數(shù):
<pre><code>
void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
</pre></code>
可以動態(tài)的將它添加到類中作為一個使用 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>
轉發(fā)方法(消息轉發(fā))和動態(tài)方法解析很大程度上是正交的。一個類有機會在轉發(fā)機制開始工作前動態(tài)解析方法滓玖。如果調用respondsToSelector: 或instancesRespondToSelector:坪哄,動態(tài)方法解析器會為選擇器提供IMP。如果實現(xiàn)resolveInstanceMethod: ,但實際上想通過轉發(fā)機制來轉發(fā)特定的選擇器翩肌,將返回NO模暗。
動態(tài)加載
一個Objective-C程序可以在運行過程中加載和鏈接新類和分類。程序中納入新代碼念祭,在開始加載的類和類別中都可以使用兑宇。
動態(tài)加載可以用來做很多不同的事情。例如粱坤,系統(tǒng)偏好設置應用程序中的模塊都是動態(tài)加載的隶糕。
在Cocoa 環(huán)境中,動態(tài)加載通常用來自定義應用程序站玄。其他人可以編寫模塊讓你的程序在運行時加載枚驻,類似IB加載自定義調色板和OS X系統(tǒng)設置應用程序加載自定義偏好模塊⊙咽玻可加載模塊可擴展應用程序测秸。他們以你允許的方式貢獻代碼疤估,但是不能自己預計和定義灾常。你提供框架,其他人提供代碼铃拇。
盡管有一個運行時函數(shù)在Mach-O 文件(在objc/objc-load.h中定義的objc_loadModules)中钞瀑,執(zhí)行 Objective-C 模塊的動態(tài)加載。Cocoa的NSBundle 類為動態(tài)加載提供了更方便的接口慷荔,這個接口是面向對象并與相關服務結合雕什。了解NSBundle 類信息和使用,可參閱基礎框架引用中的NSBundle 類規(guī)范显晶。Mach-O 文件信息可查看OS X ABI Mach-O文件格式引用贷岸。