iOS開發中的物件系統基礎

2021-07-22 13:48:04 字數 3774 閱讀 5044

[0] outline

-- [1] id和class

-- [2] 動態地操作類

-- [3] 例項化

[1] id和class

在objective-c中有乙個特別的資料型別作為物件識別符號:id,可以指向任何型別的物件。

通過 「可以指向任何型別的物件」 這一描述,猜想id實際上是指向objective-c物件系統中的基類(繼承體系中的祖先結構)的指標,在執行時是指向物件記憶體布局的基類部分。

第一眼看到id資料型別,我聯想到了python中的pyobject結構:

[cpp]view plain

copy

typedef

struct

_object  pyobject;  

該資料型別也是python物件系統中的祖先型別,不過與id相對應的應該是pyobject *型別。

id資料型別是乙個指向

structobjc_object結構的指標:

[cpp]view plain

copy

typedef

struct

objc_class *class;  

typedef

struct

objc_object  *id;  

更確切地說,id是指向class型別的指標,而class又是指向structobjc_class結構的指標:

[cpp]view plain

copy

struct

objc_class ;  

至此,可以看到objective-c物件系統的基石:structobjc_class結構:

[cpp]view plain

copy

isa指標:指向該物件所屬型別的型別物件(class object)。在objective-c中,類也是用物件來表示的,而類的isa指標指向它的metaclass(儲存靜態成員變數和類方法)。  

super_class指標:指向父類。  

name:類名稱。  

version:類的版本資訊。  

info:執行期使用的標誌位,比如0x1(cls_class)表示該類為普通class

,0x2(cls_meta)表示該類為     metaclass。  

instance_size:例項大小,即記憶體所佔空間。  

ivars:指向成員變數列表的指標。  

methodlists:根據標誌位的不同可能指向不同,比如可能指向例項方法列表,或者指向類方法列表。  

cache:因為objective-c的訊息**需要查詢dispatch table甚至可能需要遍歷繼承體系,所以快取最近使用的方法。  

protocols:類需要遵守的協議。  

[2] 動態地操作類

由上知道了類也是一種物件,那麼類物件也有一種型別,這種型別就是類的metaclass

,因此類方法其實就是metaclass的成員方法,類和metaclass是配套出現的。

那麼metaclass的isa指標和super_class指標怎麼指向的呢?

如果metaclass對應基類,那麼它的isa指向自身、super_class指標指向對應的類(基類);如果不是則isa指標指向基類的metaclass、super_class指標指向父類的metaclass。

基類的isa指標為nil。

這不禁讓我又想起了python中類似的設計思想,比如整型數字2的型別是pyintobject,而pyintobject類的型別是pytypeobject,pytypeobject的型別是pytypeobject。最終止於此。

同樣地,python中也有metaclass的存在。

知道了類的表示結構,我們可以動態地對類進行操作,加深理解。

[cpp]view plain

copy

////  main.m

//  hellooc

////  created by jason lee on 12-2-17.

//#import 

#import 

#import 

void

selfintro(idself, sel_cmd);  

intmain (

intargc, constchar * argv)  

object_setinstancevariable(demo, "myvar"

, nil);  

void

*outvalue = (

void

*)0x1;  

object_getinstancevariable(demo, "myvar"

, &outvalue);  

if(nil == outvalue)   

object_dispose(demo);  

}  return0;  

}  void

selfintro(idself, sel_cmd)   

nslog(@"%p, %@"

, isa, objc_getmetaclass(class_getname([isa 

class

])));  

isa = isa->isa; //then, isa is assigned to nsdemo's metaclass

}  }  

[3] 例項化

要例項化出乙個物件,需要根據類的定義來進行。類的定義包括類名稱、資料和運算元據的方法。

編譯過程,類的資訊會被記錄下來,供runtime system使用,同時編譯器會為每個類建立唯一的乙個物件來表示它:class object。如果從功能上說,class object也是factory object,它能夠執行類方法,負責建立例項。

從這個角度來看,我在思考class object是否就是metaclass,但是不能確認。

」,但metaclass並不能作為例項原型。

於是我認為class object是執行時class和metaclass結合起來的受限表現,能夠訪問編譯器捕捉下來的類資訊,沒有成員變數,不能呼叫成員方法,但是可以執行類方法。

從原始碼層次來看,class object是由類名來表示,比如下述**中:

[cpp]view plain

copy

intversion = [nsstring version];  

nsstring代表著class object。

首先,class object會被runtime system傳送initialize訊息進行初始化,讓其做好執行時的準備,比如初始化靜態變數。

之後,可以呼叫class object的方法(類方法)alloc來為新的例項物件分配記憶體空間,將其所有變數初始化為0,isa指標指向所屬類。

最後再呼叫init函式進行必要的初始化。

寫到這裡的時候,突然要變更辦公位置,思路被打斷了,就先寫到這裡。

最後,留乙個在so上面看到的問題,我也疑惑,只能有幾分猜測:

[這篇文章是我對so上的問題的解答:

[last updated] 2012-03-17

jason lee @ 杭州

部落格:微博:

github: 

iOS開發基礎

1 乙個應用程式是怎麼啟動的?當我們基於xcode模版建立應用程式時,應用程式啟動時大部分的環境引數會被自動設定。uikit框架提供了乙個應用程式需要構建和管理它的使用者介面的所有類 啟動 結束應用程式,控制介面和觸點事件 uikit是cocoa touch提供的眾多物件導向框架中的乙個。cocoa...

IOS 開發之Object C中的物件詳解

ioswww.cppcns.com 開發之object c中的物件詳解 前言關於c語言的基礎部分已經記錄完畢,接下來就是學習object c了,編寫oc程式需要使用foundation框架。下面就是對oc中的物件介紹。物件物件和結構類似,乙個物件可以儲存多個相關的資料。在結構中,我們稱這些資料為成員...

IOS中的Swift基礎(類和物件)

person.swift import foundation 類是一類物體的共有性抽象 物件是某一類的乙個具體 class person nsobject 該方法是為了解決字典裡面的一些 key值,在該模型裡面沒有導致的系統崩潰 override func setvalue value anyobj...