在Object-C的類型結構中,有幾個比較重要的概念:Object(實例),Class(類),Metaclass(元類),Rootclass(根類),Rootclass‘s metaclass(根元類),且這些都是對象。所以標題中的「obj」這個對象能夠是上面五個概念的任意一個,須要一一探討。
測試
1.obj爲Object實例對象
在Object-C中,Object本質上是一個struct,在這個struct中會保存一個名爲isa的指針,該指針會指向該Object的類。定義以下所示:指針
typedef struct objc_object { Class isa; } *id;
下面是代碼測試:code
//obj爲實例變量 id obj = [TestObject new]; Class cls = object_getClass(obj); Class cls2 = [obj class]; NSLog(@"%p" , cls); NSLog(@"%p" , cls2);
輸出結果:對象
2015-12-17 14:08:32.196 TestProject[658:29503] 0x100001140 2015-12-17 14:08:32.197 TestProject[658:29503] 0x100001140
結論:當obj爲實例變量時,object_getClass(obj)與[obj class]輸出結果一直,均得到isa指針,即指向類對象的指針。ci
2.obj爲Class類對象
在Objective-C中,任何類的定義都是對象。類和類的實例(對象)沒有任何本質上的區別。任何對象都有isa指針。get
typedef struct objc_class *Class; struct objc_class { Class isa; Class super_class; /* followed by runtime specific details... */ };
下面是代碼測試:class
//obj爲實例變量 id obj = [TestObject new]; //classObj爲類對象 Class classObj = [obj class]; Class cls = object_getClass(classObj); Class cls2 = [classObj class]; NSLog(@"%p" , cls); NSLog(@"%p" , cls2);
輸入結果:變量
2015-12-17 14:25:48.785 TestProject[813:38336] 0x100001118 2015-12-17 14:25:48.786 TestProject[813:38336] 0x100001140
結論:當obj爲類對象時,object_getClass(obj)返回類對象中的isa指針,即指向元類對象的指針;[obj class]返回的則是其自己。object
3.obj爲Metaclass類對象
Metaclass與Class的結構是同樣的,只是職能不一樣。Class結構中是存儲Object實例的相關數據,而Metaclass則是存儲Class相關的數據。meta
下面的測試代碼:
//obj爲實例變量 id obj = [TestObject new]; //classObj爲類對象 Class classObj = [obj class]; //metaClassObj爲元類對象 Class metaClassObj = object_getClass(classObj); Class cls = object_getClass(metaClassObj); Class cls2 = [metaClassObj class]; NSLog(@"%p" , cls); NSLog(@"%p" , cls2);
輸出結果:
2015-12-17 14:41:23.386 TestProject[921:47694] 0x7fff78fb9118 2015-12-17 14:41:23.387 TestProject[921:47694] 0x100001118
結論:當obj爲Metaclass(元類)對象時,object_getClass(obj)返回元類對象中的isa指針,由於元類對象的isa指針指向根類,全部返回的是根類對象的地址指針;[obj class]返回的則是其自己。
4.obj爲Rootclass類對象
Rootclass顧名思義就是根類,任何類的Metaclass中的isa指針都是指向根類。且結構與Class結構是同樣的。
測試代碼:
//obj爲實例變量 id obj = [TestObject new]; //classObj爲類對象 Class classObj = [obj class]; //metaClassObj爲元類對象 Class metaClassObj = object_getClass(classObj); //rootClassObj爲元類對象 Class rootClassObj = object_getClass(metaClassObj); Class cls = object_getClass(rootClassObj); Class cls2 = [rootClassObj class]; NSLog(@"%p" , cls); NSLog(@"%p" , cls2);
輸出結果:
2015-12-17 14:52:34.633 TestProject[965:54693] 0x7fff78fb9118 2015-12-17 14:52:34.634 TestProject[965:54693] 0x7fff78fb9118
結論:當obj爲Rootclass(元類)對象時,object_getClass(obj)返回根類對象中的isa指針,由於根類對象的isa指針指向Rootclass‘s metaclass(根元類),即返回的是根元類的地址指針;[obj class]返回的則是其自己。
由於根類的isa指針實際上是指向自己的,全部根元類其實就是根類,全部輸出的結果是同樣的。
總結:經上面初步的探索得知,object_getClass(obj)返回的是obj中的isa指針;而[obj class]則分兩種狀況:一是當obj爲實例對象時,[obj class]中class是實例方法:- (Class)class,返回的obj對象中的isa指針;二是當obj爲類對象(包括元類和根類以及根元類)時,調用的是類方法:+ (Class)class,返回的結果爲其自己。
最後,奉上一張經典的Object-C的對象模型圖: