iOS-底層原理 10:strong&copy&weak底層分析 以及 方法簽名和attribute簡寫含義

iOS 底層原理 文章匯總

在clang編譯的cpp文件中可以發(fā)現(xiàn) strong & copy & weak 修飾的屬性在編譯的底層代碼中是有區(qū)別的

strong & copy & weak 底層分析

  • 在LGPerson中我們定義了兩個兩個屬性,分別用copy和strong修飾


    定義類
  • clangmain.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源碼中的如下方法


對應(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é)論

  • copystrong修飾的屬性在底層編譯的不一致,主要還是llvm中對其進(jìn)行了不同的處理的結(jié)果。copy的賦值是通過objc_setProperty,而strong的賦值時通過self + 內(nèi)存平移(即將指針通過平移移至name所在的位置,然后賦值),然后還原成 strong類型

  • strong & copy 在底層調(diào)用objc_storeStrong,本質(zhì)是新值retain,舊值release

  • weak 在底層調(diào)用objc_initWeak

補(bǔ)充知識: Type Encoding & Property Type String

Type Encoding-官方文檔

Property Type String-官方文檔

clang中的方法簽名

Type encoding

clang中編譯后,方法列表的這些字符的含義是什么


clang編譯后的方法列表

@16@0:8為例

  • @16表示返回字符串占用16個字節(jié) -- 第二個@8字節(jié), sel8字節(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)的以下列表


Type encoding表

clang編譯后的屬性的attribute

clang編譯輸出了屬性的attribute ,同樣也可以通過property_getAttributes方法獲取

clang編譯后的attribute

  • T 表示 type
  • @ 表示 變量類型
  • C 表示 copy
  • N 表示 nonatomic
  • V 表示 variable 變量,即下劃線變量 _nickName

更多的可以查看官網(wǎng)的以下列表


property type string表
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容