【it168技術】在前文《深入淺出cocoa之類與物件
》一文中,我已經詳細介紹了objc中的 class 與 object 的概念,今天我們來如何在執行時動態建立類。下面這個函式就是應用前面講到的class,metaclass的概念,在執行時動態建立乙個類。這個函式來自《inside mac os x-the objective-c programming language》。
#import
#import
bool createclassdefinition(
const char * name,
const char * superclassname)
// 確保要建立的類不存在
if (objc_lookupclass (name) != nil)
// 查詢 root class,因為 meta class 的 isa 指向 root class 的 meta class
root_class = super_class;
while( root_class->super_class != nil )
// 為 class 及其 meta class 分配
記憶體new_class = calloc(
2, sizeof(struct objc_class) );
meta_class = &new_class[
1];// 設定 class
new_class->isa = meta_class;
new_class->info = cls_class;
meta_class->info = cls_meta;
// 拷貝類名字,這裡為了提高效率,讓 class 與 meta class 都指向同乙個類名字串
new_class->name = malloc (strlen (name) +
1);strcpy ((char*)new_class->name, name);
meta_class->name = new_class->name;
// 分配並置空 method lists,我們可以在之後使用 class_addmethods 向類中增加方法
new_class->methodlists = calloc(
1, sizeof(struct objc_method_list *) );
meta_class->methodlists = calloc(
1, sizeof(struct objc_method_list *) );
// 將類加入到繼承體系中去:
// 1,設定類的 super class
// 2,設定 meta class 的 super class
// 3,設定 meta class 的 isa
new_class->super_class = super_class;
meta_class->super_class = super_class->isa;
meta_class->isa = (void *)root_class->isa;
// 最後,將 class 註冊到執行時系統中
objc_addclass( new_class );
return yes; }
如果要在**中使用執行時相關的函式,我們需要匯入 libobjc.dylib,並匯入相關的標頭檔案(比如這裡的 runtime.h)。
在前文中總結到「objc 為每個類的定義生成兩個 objc_class ,乙個即普通的 class,另乙個即 metaclass。我們可以在執行期建立這兩個 objc_class 資料結構,然後使用 objc_addclass 動態地建立新的類定義。」,這在上面的**中就體現出來了:new_class 和 meta_class 就是新類所必須的兩個 objc_class。其他的**就不解釋了,注釋以及**足以自明了。
在實際的運用中,我們使用 objc 執行時函式來動態建立類:
class objc_allocateclasspair(class superclass, const char *name, size_t extrabytes);
譬如:
#import
#import
void reportfunction(id self, sel _cmd)
nslog(@
">> nsobject's class is %p
", [nsobject class]); (
在oc源**中object.m
- class
+ class
可以了解到nsobject呼叫的是類方法 返回接收者 )
nslog(@
">> nsobject's meta class is %p
", object_getclass([nsobject class]));
}int
main (
intargc,
const
char * argv)
return 0;
} 在上面的**中,我們建立繼承自 nsstring 的子類 nsstringsubclass,然後向其中新增方法 report,並在執行時系統中註冊,這樣我們就可以使用這個新類了。在這裡使用 performselector 來向新類的物件傳送訊息,可以避免編譯警告資訊(因為我們並沒有宣告該類及其可響應的訊息)。
執行結果為:
>> this
object
is 0x100114710.
>> class
is nsstringsubclass,
and super
is nsstring.
>> following the isa pointer
1 times gives 0x100114410
>> following the isa pointer
2 times gives 0x100114560
>> following the isa pointer
3 times gives 0x7fff7e257b50
>> nsobject
's class is 0x7fff7e257b78
>> nsobject
's meta class is 0x7fff7e257b50
根據前文中的類關係圖,我們不難從執行結果中分析出 nsstringsubclass 的內部類結構:
1,物件的位址為 :0x100114710
2,class 的位址為:0x100114410
3,meta class 的位址為:0x100114560
4,meta class 的 class 位址為:0x7fff7e257b50 (也是 nsobject 的 meta class)
5,nsobject 的 meta class 的 meta class 是其自身
執行時建立類
a.使用objc allocateclasspair建立乙個類class const char classname calculator class kclass objc getclass classname if kclass b.使用class addivar新增乙個成員變數 nsuinteg...
OC執行時訊息
訊息傳送 本章描述內容 訊息表示式是如何轉化成objc msgsend函式呼叫,和 如何通過明知呼叫方法。然後說明如何利用objc msgsend函式,並且,有必要時,如何繞開動態繫結。objc msgsend函式 在oc中,程式執行之前,訊息是不會繫結到方法實現的。編譯器會將乙個訊息表示式轉化 r...
C 在執行時動態建立型別
c 在執行時動態的建立型別,這裡是通過動態生成c 源 然後通過編譯器編譯成程式集的方式實現動態建立型別 public static assembly newassembly n private system.componentmodel.icontainer components null npro...