在clang編譯的cpp文件中可以發(fā)現(xiàn) strong & copy & weak 修飾的屬性在編譯的底層代碼中是有區(qū)別的
strong & copy & weak 底層分析
-
在LGPerson中我們定義了兩個(gè)兩個(gè)屬性倒堕,分別用copy和strong修飾
-
用
clang
將main.m
文件編譯成main.cpp
,然后發(fā)現(xiàn)copy 和strong
修飾的屬性的set
方法是有區(qū)別的
這里就有疑問了,為什么copy修飾的屬性使用了objc_setProperty联予,而strong修飾的沒有
徘跪?
-
在LLVM中搜索
”objc_setProperty
模软,找到如下所示的getOptimizedSetPropertyFn
方法中
從這里即可看出雁仲,針對(duì)不同的修飾符疗我,返回的那么是不同的 如果是
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
上述的幾個(gè)name分別對(duì)應(yīng)objc-781源碼中的如下方法
然后通過匯編調(diào)試發(fā)現(xiàn),最終都會(huì)走到objc_storeStrong
-
copy修飾的屬性匯編調(diào)試結(jié)果
-
strong修飾的屬性匯編調(diào)試結(jié)果
源碼中搜索
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
方法甸饱,如下圖所示,發(fā)現(xiàn)copy 和 strong修飾的屬性執(zhí)行的策略是不一致的
-
llvm中搜索
EmitARCStoreStrongCall
方法仑濒,在GenerateCopyHelperFunction
方法有調(diào)用叹话,然后在這里發(fā)現(xiàn)了strong 和 weak的不同處理
其中BlockCaptureEntityKind有如下的枚舉值以及表示的含義
-
如果是weak修飾,執(zhí)行
EmitARCCopyWeak
方法墩瞳,如下所示驼壶,weak在底層的調(diào)用是objc_initWeak
如果是strong修飾,執(zhí)行
EmitARCStoreStrongCall
方法
-
結(jié)論
copy
和strong
修飾的屬性在底層編譯的不一致喉酌,主要還是llvm中對(duì)其進(jìn)行了不同的處理的結(jié)果热凹。copy
的賦值是通過objc_setProperty
,而strong的賦值時(shí)通過self + 內(nèi)存平移
(即將指針通過平移移至name所在的位置泪电,然后賦值)般妙,然后還原成strong
類型strong & copy
在底層調(diào)用objc_storeStrong
,本質(zhì)是新值retain歪架,舊值release
weak
在底層調(diào)用objc_initWeak
補(bǔ)充知識(shí): Type Encoding & Property Type String
clang中的方法簽名
Type encoding
clang中編譯后股冗,方法列表的這些字符的含義是什么
以@16@0:8
為例
- @16表示返回字符串占用16個(gè)字節(jié) -- 第二個(gè)
@
占8
字節(jié),sel
占8
字節(jié)-
第一個(gè)@
表示返回值
-
16
表示 總共占用的字節(jié)數(shù)16
字節(jié) - 第二個(gè)@:第一個(gè)參數(shù)
- id -- @ 統(tǒng)配類型
- typedef struct objc_object *id
- 0 -- 從0開始 0-8
- : -- 代表sel和蚪,方法編號(hào)
- 8 -- 8-16
-
- 而v24@0:8@16中的 v -- void 無返回值
更多的可以查看官網(wǎng)的以下列表
clang編譯后的屬性的attribute
clang編譯輸出了屬性的attribute
止状,同樣也可以通過property_getAttributes
方法獲取
-
T
表示type
-
@
表示變量類型
-
C
表示copy
-
N
表示nonatomic
-
V
表示variable
變量,即下劃線變量_nickName
更多的可以查看官網(wǎng)的以下列表