前言
- 目前打算深入一下OC和Swift的底層探究,希望自己有所提升,并能分享一些收獲。
這篇主要記錄:通過查看objc的源碼探索alloc&init
- 在這里給大家介紹一位大牛已經配置好的源碼GitHub,我們直接下載就可以使用了。
1. 下載之后,經過一些配置,真機編譯 ,然后來到如下調試界面
注:allocwithZone 基本被舍棄沒用了;一般情況下 alloc 和 allocwithZone 的作用是一樣的,alloc和allocWithZone都可以用于創建實例,實際上alloc會默認調用allocWithZone方法;
2.接下來我們來到:_class_createInstanceFromZone
(類從區域創建實例)方法里面 這里有三個重要步驟
注:
- a. 可以發現alloc具有
申請內存空間
、創建對象
、并給指針賦予地址的能力
; - b. 獲取實例的內存空間大小:
cls->instanceSize()
- c. 根據內存大小,分配內存空間,讓實例指向內存開始地址:
calloc
- d.
關聯isa
,實例的isa指向類:obj->initInstanceIsa(cls, hasCxxDtor)
- e:關于
word_align
字節對齊(x + WORD_MASK) & ~WORD_MASK
這個算法是為了讓isa
對象需要的內存空間是8的倍數-8字節對齊,mallocSize
系統分配的內存大小是16字節對齊的計算屬性方法等。作用:內存對齊,讓CPU讀取更加方便,用空間來換取時間
3 .總結alloc 全部流程(來自百度):
alloc
4.探索init,new方法
id _objc_rootInit(id obj)
{
return obj;
}
返回的就是alloc出來的obj。
- (id)init {
return _objc_rootInit(self);
}
init沒做任何操作,一般在這里是工廠方式來重寫方法,自定義,我們經常會這樣寫代碼
- (instancetype)init{
self = [super init];
if (self) {
[self doSomething];
}
return self;
}
//
[super init] 重寫父類的方法 防止覆蓋父類的方法
self = [super init]
= 是確認繼承父類 可以延伸自己的方法
if(self)做判斷處理 防止父類在init的時候return nil
做一個安全的處理 不然子類的實現就沒有意義了
通過源碼,看出new
就是callAlloc
+init
的組合實現
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}
5. 拓展:
-
編譯優化
:fastpath 、slowpath 進行是否需要編譯優化的判斷 ,release模式下都會進行編譯優化,執行fastpath判斷,作用
:減少編譯時間,鏈接時間,運行時間,優化空閑時間;
轉載:iOS 查看項目編譯時間并優化編譯速度方法 - 打印語句記錄:
po
與p
:p
表示"expression
"——打印對象指針;
po
是"expression -O
"——打印對象本身;
x/4gx
對象 ——表示輸出4個16進制的8字節地址空間(x表示16進 制,4表示4個,g表示8字節為單位,等同于x/4xg 對象);
x 對象——表示以16進制打印對象內存地址(x表示16進制);
6. 總結:
通過查看objc的源碼探索alloc&init,我們可以大致看清alloc的執行步驟,這篇主要講了其整體的流程,主要核心就是來到_class_createInstanceFromZone
,這個方法告訴我們內存是如何開辟的,內存是如何分配的,當前類和指針地址的關系。接下再來深入探索,開辟分配內存的細節和對象中的屬性對內存分配的影響。