在clang編譯的cpp文件中可以發現 strong & copy & weak 修飾的屬性在編譯的底層代碼中是有區別的
strong & copy & weak 底層分析
-
在LGPerson中我們定義了兩個兩個屬性,分別用copy和strong修飾
定義類 -
用
clang
將main.m
文件編譯成main.cpp
,然后發現copy 和strong
修飾的屬性的set
方法是有區別的
clang編譯后的屬性的set、get方法
這里就有疑問了,為什么copy修飾的屬性使用了objc_setProperty,而strong修飾的沒有
?
-
在LLVM中搜索
”objc_setProperty
,找到如下所示的getOptimizedSetPropertyFn
方法中
objc_setProperty底層編譯
從這里即可看出,針對不同的修飾符,返回的那么是不同的 如果是
atomic & copy
修飾,name為objc_setProperty_atomic_copy
如果是
atomic 且沒有copy
修飾,name為objc_setProperty_atomic
如果是
nonatomic & copy
修飾,name為objc_setProperty_nonatomic_copy
其他剩余的組合,即
nonatomic、nonatomic & strong、nonatomic & weak
等,name為objc_setProperty_nonatomic
上述的幾個name分別對應objc-781源碼中的如下方法
然后通過匯編調試發現,最終都會走到objc_storeStrong
-
copy修飾的屬性匯編調試結果
copy匯編調試 -
strong修飾的屬性匯編調試結果
strong匯編調試 源碼中搜索
objc_storeStrong
,有如下源碼,主要也是retain新值,release舊值
void
objc_storeStrong(id *location, id obj)
{
id prev = *location;
if (obj == prev) {
return;
}
objc_retain(obj);//retain新值
*location = obj;
objc_release(prev);//release舊值
}
-
llvm編譯源碼中搜索
objc_storeStrong
,找到EmitARCStoreStrongCall
方法,如下圖所示,發現copy 和 strong修飾的屬性執行的策略是不一致的
EmitARCStoreStrongCall底層 -
llvm中搜索
EmitARCStoreStrongCall
方法,在GenerateCopyHelperFunction
方法有調用,然后在這里發現了strong 和 weak的不同處理
GenerateCopyHelperFunction底層編譯
其中BlockCaptureEntityKind有如下的枚舉值以及表示的含義
BlockCaptureEntityKind枚舉值-
如果是weak修飾,執行
EmitARCCopyWeak
方法,如下所示,weak在底層的調用是objc_initWeak
EmitARCCopyWeak底層編譯 如果是strong修飾,執行
EmitARCStoreStrongCall
方法
-
結論
copy
和strong
修飾的屬性在底層編譯的不一致,主要還是llvm中對其進行了不同的處理的結果。copy
的賦值是通過objc_setProperty
,而strong的賦值時通過self + 內存平移
(即將指針通過平移移至name所在的位置,然后賦值),然后還原成strong
類型strong & copy
在底層調用objc_storeStrong
,本質是新值retain,舊值release
weak
在底層調用objc_initWeak
補充知識: Type Encoding & Property Type String
clang中的方法簽名
Type encoding
clang中編譯后,方法列表的這些字符的含義是什么
以@16@0:8
為例
- @16表示返回字符串占用16個字節 -- 第二個
@
占8
字節,sel
占8
字節-
第一個@
表示返回值
-
16
表示 總共占用的字節數16
字節 - 第二個@:第一個參數
- id -- @ 統配類型
- typedef struct objc_object *id
- 0 -- 從0開始 0-8
- : -- 代表sel,方法編號
- 8 -- 8-16
-
- 而v24@0:8@16中的 v -- void 無返回值
更多的可以查看官網的以下列表
clang編譯后的屬性的attribute
clang編譯輸出了屬性的attribute
,同樣也可以通過property_getAttributes
方法獲取
-
T
表示type
-
@
表示變量類型
-
C
表示copy
-
N
表示nonatomic
-
V
表示variable
變量,即下劃線變量_nickName
更多的可以查看官網的以下列表