在clang編譯的cpp文件中可以發(fā)現(xiàn) strong & copy & weak 修飾的屬性在編譯的底層代碼中是有區(qū)別的
strong & copy & weak 底層分析
-
在LGPerson中我們定義了兩個兩個屬性,分別用copy和strong修飾
定義類 -
用
clang將main.m文件編譯成main.cpp,然后發(fā)現(xiàn)copy 和strong修飾的屬性的set方法是有區(qū)別的
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分別對應(yīng)objc-781源碼中的如下方法

然后通過匯編調(diào)試發(fā)現(xiàn),最終都會走到objc_storeStrong
-
copy修飾的屬性匯編調(diào)試結(jié)果
copy匯編調(diào)試 -
strong修飾的屬性匯編調(diào)試結(jié)果
strong匯編調(diào)試 源碼中搜索
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í)行的策略是不一致的
EmitARCStoreStrongCall底層 -
llvm中搜索
EmitARCStoreStrongCall方法,在GenerateCopyHelperFunction方法有調(diào)用,然后在這里發(fā)現(xiàn)了strong 和 weak的不同處理
GenerateCopyHelperFunction底層編譯
其中BlockCaptureEntityKind有如下的枚舉值以及表示的含義
BlockCaptureEntityKind枚舉值-
如果是weak修飾,執(zhí)行
EmitARCCopyWeak方法,如下所示,weak在底層的調(diào)用是objc_initWeak
EmitARCCopyWeak底層編譯 如果是strong修飾,執(zhí)行
EmitARCStoreStrongCall方法
-
結(jié)論
copy和strong修飾的屬性在底層編譯的不一致,主要還是llvm中對其進(jìn)行了不同的處理的結(jié)果。copy的賦值是通過objc_setProperty,而strong的賦值時通過self + 內(nèi)存平移(即將指針通過平移移至name所在的位置,然后賦值),然后還原成strong類型strong & copy在底層調(diào)用objc_storeStrong,本質(zhì)是新值retain,舊值releaseweak在底層調(diào)用objc_initWeak
補(bǔ)充知識: Type Encoding & Property Type String
clang中的方法簽名
Type encoding
clang中編譯后,方法列表的這些字符的含義是什么

以@16@0:8為例
- @16表示返回字符串占用16個字節(jié) -- 第二個
@占8字節(jié),sel占8字節(jié)-
第一個@表示返回值 -
16表示 總共占用的字節(jié)數(shù)16字節(jié) - 第二個@:第一個參數(shù)
- id -- @ 統(tǒng)配類型
- typedef struct objc_object *id
- 0 -- 從0開始 0-8
- : -- 代表sel,方法編號
- 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)的以下列表









