OC執行時動態建立類

2021-06-15 05:35:59 字數 3461 閱讀 1169

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...