物件是如何初始化的(iOS)

發表於2016-08-09

關注倉庫,及時獲得更新:iOS-Source-Code-Analyze

Follow: Draveness · Github

在之前,我們已經討論了非常多的問題了,關於 objc 原始碼系列的文章也快結束了,其實關於物件是如何初始化的這篇文章本來是我要寫的第一篇文章,但是由於有很多前置內容不得不說,所以留到了這裡。

+ alloc- init 這一對我們在 iOS 開發中每天都要用到的初始化方法一直困擾著我, 於是筆者仔細研究了一下 objc 原始碼中 NSObject 如何進行初始化。

在具體分析物件的初始化過程之前,我想先放出結論,以免文章中的細枝末節對讀者的理解有所影響;整個物件的初始化過程其實只是為一個分配記憶體空間,並且初始化 isa_t 結構體的過程

alloc 方法分析

先來看一下 + alloc 方法的呼叫棧(在呼叫棧中省略了很多不必要的方法的呼叫):open

這個呼叫棧中的方法涉及了多個檔案中的程式碼,在下面的章節中會對呼叫的方法逐步進行分析,如果這個呼叫棧讓你覺得很頭疼,也不是什麼問題。

alloc 的實現

alloc 方法的實現真的是非常的簡單, 它直接呼叫了另一個私有方法 id _objc_rootAlloc(Class cls)

這就是上帝類 NSObjectcallAlloc 的實現,我們省略了非常多的程式碼,展示了最常見的執行路徑:

物件初始化中最重要的操作都在 _class_createInstanceFromZone 方法中執行:

物件的大小

在使用 calloc 為物件分配一塊記憶體空間之前,我們要先獲取物件在記憶體的大小:

例項大小 instanceSize 會儲存在類的 isa_t 結構體中,然後經過對齊最後返回。

Core Foundation 需要所有的物件的大小都必須大於或等於 16 位元組。

在獲取物件大小之後,直接呼叫 calloc 函式就可以為物件分配記憶體空間了。

isa 的初始化

在物件的初始化過程中除了使用 calloc 來分配記憶體之外,還需要根據類初始化 isa_t 結構體:

上面的程式碼只是對 isa_t 結構體進行初始化而已:

在這裡並不想過多介紹關於 isa_t 結構體的內容,你可以看從 NSObject 的初始化了解 isa 來了解你想知道的關於 isa_t 的全部內容。

init 方法

NSObject- init 方法只是呼叫了 _objc_rootInit 並返回了當前物件:

總結

在 iOS 中一個物件的初始化過程很符合直覺,只是分配記憶體空間、然後初始化 isa_t 結構體,其實現也並不複雜,這篇文章也是這個系列文章中較為簡單並且簡短的一篇。

關注倉庫,及時獲得更新:iOS-Source-Code-Analyze

Follow: Draveness · Github

原文連結: http://draveness.me/object-init

相關文章