標籤:ios開發 nsobject objective-c 深入學習
先來看看NSObject的主要定義如下所示(包括一些我的理解注釋):
@interface NSObject <NSObject> { Class isa OBJC_ISA_AVAILABILITY;}/* Initializing a Class *//** * @author Arbboter, 15-01-15 22:01:47 * * 如果當前類或者分類實現了load方法才會調用該方法,否則調用父類的方法。 * 是麼時候調用該方法:當類或者其分類在靜態連結或者動態載入的時候調用該方法 * 因此,當import類的標頭檔的時候,會調用load方法 */+ (void)load;/** * @author Arbboter, 15-01-15 22:01:37 * * 在runtime時第一次調用類的方法(執行個體方法或者類方法,不包括load方法) * 前會調用該方法,而且顯示調用層次是從父類到子類(這一點和對象的初始化一致)。 * 如果子類沒有實現該方法,會直接調用父類的,需要注意的是,如果有繼承層次為: * class_1 <- class_2 <- class_3 * 而只有class_1實現了該方法,那麼建立一個clsaa_3的對象的時候,會調用該方法 * 三次(每一層類都會調用該方法),且都是class_1實現的方法 */+ (void)initialize;/* Creating, Copying, and Deallocating Objects *//** * @author Arbboter, 15-01-15 22:01:57 * 建立一個當前類的執行個體變數所需的記憶體 * @param zone 已經忽略 * @return 分配的對象 */+ (instancetype)allocWithZone:(struct _NSZone *)zone;/** * @author Arbboter, 15-01-15 23:01:06 * 由於曆史問題,該方法會調用allocWithZone方法建立對象記憶體 * @return 分配了記憶體的對象 */+ (instancetype)alloc;/** * 初始化對象的isa為描述類的資料結構,其他的執行個體變數為0 */- (instancetype)init;/** * @author Arbboter, 15-01-15 23:01:57 * 相當於 [[類名 alloc] init] * @return 初始化好的對象 */+ (instancetype)new;/** * @author Arbboter, 15-01-15 23:01:49 * 由NSCopying協議定義的copyWithZone:方法返回的對象 * @return copy出的對象 */- (id)copy;/** * @author Arbboter, 15-01-15 23:01:49 * 由NSMutableCopying協議定義的mutableCopyWithZone:方法返回的對象 * @return copy出的對象 */- (id)mutableCopy;/** copy協議 */+ (id)copyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;+ (id)mutableCopyWithZone:(struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;/** 釋放銷毀對象 */- (void)dealloc;/** 其他的方法這裡不予討論了 */@end
首先需要注意的兩個方法是load和initialize的調用次序和時機。load是當類的標頭檔或者其擴充被import的時候就會調用,不管有沒有使用該類,而initialize是在類的方法被第一次調用前會被調用。更多的細節問題比較煩,代碼中的注釋相對二樣更詳盡一點。
接下來來看看NSObject的一個唯一成員變數isa,該變數的類型是Class。通過查看Class的定義以及相關的類型定義,你會發現一個很有趣的事實,如下所示:
/** Objective-C對象的定義 */@interface NSObject <NSObject>{ /** 指向當前類的執行個體所在的類的一個指標 */ Class isa OBJC_ISA_AVAILABILITY;}/* 一些方法的定義 */@end/** Objective-C對象的結構體的定義 * 用於儲存對象的狀態(執行個體變數) */struct objc_object{ Class isa OBJC_ISA_AVAILABILITY;};/** Objective-C對象的類的定義 * 用於儲存對象的方法 */struct objc_class{ Class isa OBJC_ISA_AVAILABILITY; /** 以下省略了oc1.0版本定義的部分 */} OBJC2_UNAVAILABLE;typedef struct objc_class *Class; // 指向類結構的指標typedef struct objc_object *id; // 指向Objective-C對象結構體的指標
從上面的定義我們發現了之前所提到的Class和我們熟悉的id的定義,同時發現了一個奇怪的現象。結構體objc_object、objc_class和NSObject的成員變數居然一模一樣,都是
Class isa OBJC_ISA_AVAILABILITY;
這是為什麼呢?大家可以看看《Objective-C的物件模型分析》這篇文章,然後再回頭看這個問題或許就能看出一些名堂了。其實NSObeject是Objective-C的幾乎全部對象的基類,該類定義了類的狀態資訊(變數)和方法(類方法和執行個體方法),而Class是用於指向儲存NSObeject的方法資訊的指標,id用於儲存NSObject的狀態資訊的指標,兩個一起協作一起更好地描述NSObject。每個Objective-C的對象的成員變數isa指向的是這個對象的類資訊,同時isMemberOfClass:方法就就是根據isa資訊來判斷的。
通過分析,我們可以發現類其實也是一個對象。當我們定義一個類的時候,實際上定義了兩個類,一個類是我們看得到的類,一個類是我們看不到的同名元類,而我們看到的類就是該元類的對象。(具體可看看之前提到的那篇文章)
(沒思路,理清了再來補充)
深入學習Objective-C的NSObject