筆者翻譯自iOS Developer Library Dynamic Method Resolution
動態方法解決方案
這章解釋了如何動態地提供一個方法的實現。
動態方法解決方案
有時候,你可能想動態地提供一個方法的實現。例如:Object-C 聲明屬性特性(參考 Object-C 編程語言中聲明屬性) 時包含了 @dynamic
指令:
<pre><code>@dynamic propertyName;
</code></pre>
這樣就告訴編譯器與該屬性相對應的方法將被動態提供。
你能實現 resolveInstanceMethod:
和 resolveClassMethod:
函數分別為實例方法和類方法提供動態方法實現。
Object-C 方法僅僅是一個至少帶有兩個參數(self 和 _cmd)的C函數。你能使用 class_addMethod
給類添加一個函數作為類中的方法。
<pre><code>void dynamicMethodIMP(id self, SEL _cmd) {
// implementation ....
}
</code></pre>
你能使用 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
</code></pre>
消息轉發(詳見:Message Forwarding)和動態方法解決方案是相交的。一個類有機會在轉發機制實現之前實現動態方法解決方案。如果 respondsToSelector:
和 instancesRespondToSelector:
被調用,動態方法解決器將優先給函數選擇器提供機會使它能綁定一個方法實現。如果你實現了 resolveInstanceMethod:
,但希望指定的選擇器被轉發機制轉發,你應該為這些選擇器返回 NO。
動態加載
Object-C 程序能在運行時加載和鏈接新的類和分類。新的代碼將整合到程序中,并且與程序一開始加載的類和分類同等對待。
動態加載能被用作許多不同的情況。例如:在系統偏好應用中種類繁多的模塊被動態加載。
在 Cocoa 環境中,動態加載通常被用作能被自定義定制的應用。其他人可以編寫能在你的程序運行時加載的模塊——就像 Interface Builder 加載用戶調色板和 OS X 系統偏好設置應用加載用戶偏好模塊。這些可加載的模塊擴展了你的應用功能。它們通過你允許但是你不能預測和自定義的方式實現。你提供了框架,但其他人提供代碼。
盡管在 Mach-O 文件(objc_loadModules, 在 objc/objc-load.h 中定義)中,有能夠動態加載 Object-C 模塊的運行時函數, Cocoa NSBundle
類提供了更方便的動態加載接口——它是面向對象的且集成了很多相關的服務。在 Foundation 框架說明中參考 NSBundle
類的特性并獲取更多 NSBundle
類的信息及如何使用它。參考 Mach-O 文件的 OS X ABI Mach-O File Format Reference 獲取更多信息。