本章描述了如何動態(tài)的提供一個方法的實(shí)現(xiàn)。
動態(tài)方法解析
在有些情況下,需要動態(tài)的提供一個方法的實(shí)現(xiàn)。例如,Objective-C 聲明的屬性特征(見Objective-C 編程語言中的聲明屬性)包含@dynamic指令:
<pre><code>@dynamic propertyName; </pre></code>
它告訴編譯器,將動態(tài)的提供該方法與屬性。
可以實(shí)現(xiàn)resolveInstanceMethod: 和resolveClassMethod: 方法來動態(tài)的提供一個給定選擇器的實(shí)例和對應(yīng)的類方法提供實(shí)現(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>
轉(zhuǎn)發(fā)方法(消息轉(zhuǎn)發(fā))和動態(tài)方法解析很大程度上是正交的。一個類有機(jī)會在轉(zhuǎn)發(fā)機(jī)制開始工作前動態(tài)解析方法。如果調(diào)用respondsToSelector: 或instancesRespondToSelector:,動態(tài)方法解析器會為選擇器提供IMP。如果實(shí)現(xiàn)resolveInstanceMethod: ,但實(shí)際上想通過轉(zhuǎn)發(fā)機(jī)制來轉(zhuǎn)發(fā)特定的選擇器,將返回NO。
動態(tài)加載
一個Objective-C程序可以在運(yùn)行過程中加載和鏈接新類和分類。程序中納入新代碼,在開始加載的類和類別中都可以使用。
動態(tài)加載可以用來做很多不同的事情。例如,系統(tǒng)偏好設(shè)置應(yīng)用程序中的模塊都是動態(tài)加載的。
在Cocoa 環(huán)境中,動態(tài)加載通常用來自定義應(yīng)用程序。其他人可以編寫模塊讓你的程序在運(yùn)行時加載,類似IB加載自定義調(diào)色板和OS X系統(tǒng)設(shè)置應(yīng)用程序加載自定義偏好模塊??杉虞d模塊可擴(kuò)展應(yīng)用程序。他們以你允許的方式貢獻(xiàn)代碼,但是不能自己預(yù)計(jì)和定義。你提供框架,其他人提供代碼。
盡管有一個運(yùn)行時函數(shù)在Mach-O 文件(在objc/objc-load.h中定義的objc_loadModules)中,執(zhí)行 Objective-C 模塊的動態(tài)加載。Cocoa的NSBundle 類為動態(tài)加載提供了更方便的接口,這個接口是面向?qū)ο蟛⑴c相關(guān)服務(wù)結(jié)合。了解NSBundle 類信息和使用,可參閱基礎(chǔ)框架引用中的NSBundle 類規(guī)范。Mach-O 文件信息可查看OS X ABI Mach-O文件格式引用。