Runtime

一宋列、位運算

  1. &:按位與辆布,可以用來取出特定位的值瞬矩。需要取哪一位,就將哪一位置為0锋玲。掩碼景用,一般是用來按位與運算。

         0011
        &0010
        ------
         0010
    
  2. |:按位或惭蹂,可以用來設(shè)置某一位的值伞插。需要設(shè)置哪一位,就將哪一位置為1剿干。

         0001
        |0010
        ------
         0011
    
  3. ~:按位取反

  4. #define MJRichMask (1<<1)蜂怎,代表左移一位

  5. 使用位域

    struct {
        char tall : 1; // 只使用1位,默認(rèn)開始是最右邊一位
        char rich : 1;
        char handsome : 1;
    } tallRichHandsome;
    

二置尔、isa

  1. 變化

    • 在arm64架構(gòu)之前杠步,isa就是一個普通的指針,存儲著Class榜轿、Meta-Class對象的內(nèi)存地址
    • 從arm64架構(gòu)開始幽歼,對isa進行了優(yōu)化,變成了一個共用體(union)結(jié)構(gòu)谬盐,使用位域來存儲更多的信息
        union isa_t {
        isa_t() { }
        isa_t(uintptr_t value) : bits(value) { }
    
        Class cls;
        uintptr_t bits;
    #if defined(ISA_BITFIELD)
        struct {
            ISA_BITFIELD;  // defined in isa.h
        };
    #endif
    };
        #   define ISA_BITFIELD                                                      \
          uintptr_t nonpointer        : 1;                                       \
          uintptr_t has_assoc         : 1;                                       \
          uintptr_t has_cxx_dtor      : 1;                                       \
          uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
          uintptr_t magic             : 6;                                       \
          uintptr_t weakly_referenced : 1;                                       \
          uintptr_t deallocating      : 1;                                       \
          uintptr_t has_sidetable_rc  : 1;                                       \
          uintptr_t extra_rc          : 19
    
  2. isa位域詳解

    • nonpointer

    0甸私,代表普通指針,存儲著Class飞傀、Meta-Class對象的內(nèi)存地址
    1皇型,代表優(yōu)化過诬烹,使用位域存儲更多的信息

    • has_assoc

    是否設(shè)置過關(guān)聯(lián)對象,如果沒有弃鸦,釋放時會更快

    • has_cxx_dtor

    是否有c++的析構(gòu)函數(shù)(.cxx_destruct)绞吁,如果沒有,釋放時會更快

    • shiftcls

    存儲著Class唬格、Meta-Class對象的內(nèi)存地址信息

    • magic

    用于在調(diào)試時分辨對象是否未完成初始化

    • weakly_referenced

    是否有被弱引用指向過家破,如果沒有,釋放時會更快

    • deallocating

    對象是否正在釋放

    • has_sidetable_rc

    引用計數(shù)器是否過大無法存儲在isa中
    如果為1购岗,那么引用計數(shù)會存儲在一個叫SideTable的類的屬性中

    • extra_rc

    里面存儲的值是引用計數(shù)器減1

三汰聋、Class

  1. Class結(jié)構(gòu)


    image.png
  2. class_rw_t

    • class_rw_t里邊的methods、properties喊积、protocols都是二維數(shù)組烹困,是可讀可寫的,包含了類的初始內(nèi)容注服,分類的內(nèi)容
      image.png
  3. class_ro_t

    • class_ro_t里面的baseMethodList韭邓、baseProtocols、ivars溶弟、baseProperties都是一維數(shù)組女淑,是只讀的,包含了類的初始內(nèi)容
      image.png
  4. method_t

    • method_t是對方法/函數(shù)的封裝
        struct method_t {
        SEL name; // 函數(shù)名
        const char *types; // 編碼(返回值類型辜御、參數(shù)類型)
        MethodListIMP imp; // 函數(shù)指針(函數(shù)地址)
    
        struct SortBySELAddress :
            public std::binary_function<const method_t&,
                                        const method_t&, bool>
        {
            bool operator() (const method_t& lhs,
                             const method_t& rhs)
            { return lhs.name < rhs.name; }
        };
    };
    
    • IMP代表函數(shù)的具體實現(xiàn)
    typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
    
    • SEL代表方法名/函數(shù)名鸭你,一般叫做選擇器,底層結(jié)構(gòu)跟char *類似
      * 可以通過@selector()sel_registerName()獲得
      * 可以通過sel_getName()NSStringFromSelector()轉(zhuǎn)成字符串
      * 不同類中相同名字的方法擒权,所對應(yīng)的方法選擇器是相同的
    typedef struct objc_selector *SEL;
    
    • types包含了函數(shù)返回值袱巨、參數(shù)編碼的字符串
      image.png
    • Type Encoding
      • iOS中提供了一個叫做@encode指令,可以將具體類型表示成字符串編碼
        image.png

四碳抄、方法緩存

  • Class內(nèi)部結(jié)構(gòu)中有個方法緩存(cache_t),用散列表(哈希表)來緩存曾經(jīng)調(diào)用過的方法愉老,可以提高方法的查找速度(以空間換時間)

  • 緩存查找


五、objc_msgSend()

  1. 執(zhí)行流程

    • OC中的方法剖效,其實都是轉(zhuǎn)換為objc_msgSend函數(shù)的調(diào)用
    • objc_msgSend的執(zhí)行流程可以分為3大階段
      • 消息發(fā)送
      • 動態(tài)方法解析
      • 消息轉(zhuǎn)發(fā)
  2. objc_msgSend的源碼跟讀



  3. 消息發(fā)送流程

    • receiver通過isa指針找到receiverClass
    • receiverClass通過superclass指針找到superClass
    • 如果是從class_rw_t中查找方法
      • 已經(jīng)排序的嫉入,二分查找
      • 沒有排序的,遍歷查找
  4. 動態(tài)方法解析流程

    • 可以實現(xiàn)以下方法璧尸,動態(tài)添加方法實現(xiàn)
      +resolveInstanceMethod
      +resolveClassMethod
    • 動態(tài)解析過后咒林,會重新走“消息發(fā)送”流程
      • “從receiverClass的cache中查找方法”這一步開始執(zhí)行
    • 動態(tài)方法解析例子
      • Method可以等價理解為struct method_t *
    • 補充:@dynamic告訴編譯器不用自動生成gettersetter,不用自動生成成員變量爷光,等到運行時再添加方法實現(xiàn)
  5. 消息轉(zhuǎn)發(fā)流程

    • 開發(fā)者可以在forwardInvocation方法中自定義任何邏輯
    • 以上方法都有對象方法垫竞、類方法兩種實現(xiàn)
    • NSMethodSignature的生成例子

六、super

  1. [super message]的底層實現(xiàn)

    • 消息接受者仍然是子類對象
    • 從父類開始查找方法的實現(xiàn)
  2. 使用clang轉(zhuǎn)化的c++代碼蛀序,不一定是程序最終生成的代碼欢瞪。super的調(diào)用活烙,底層其實是轉(zhuǎn)換為objc_msgSendSuper2函數(shù)的調(diào)用,接受兩個參數(shù)

    • struct objc_super2
    • SEL
    struct objc_super2 {
    id receiver; // 消息接受者
    Class current_class; // receiver的Class對象
    };
    

七遣鼓、LLVM的中間代碼(IR)

  • Objective-C在變?yōu)闄C器代碼之前瓣颅,會被LLVM編譯器轉(zhuǎn)換為中間代碼(Intermediate Representation)
  • 可以使用以下命令行指令生成中間代碼
    clang -emit-llvm -S main.m
  • 語法簡介
  • 具體可以參考官方文檔:https://llvm.org/docs/LangRef.html

八、Runtime API

    • 動態(tài)創(chuàng)建一個類(參數(shù):父類譬正,類名,額外的內(nèi)存空間)
      Class _Nullable objc_allocateClassPair(Class _Nullable superclass, const char * _Nonnull name, size_t extraBytes)
    • 注冊一個類(需要在類注冊之前添加成員變量)
      void objc_registerClassPair(Class _Nonnull cls)
    • 銷毀一個類
      void objc_disposeClassPair(Class _Nonnull cls)
    • 獲取isa指向的Class
      Class object_getClass(id obj)
    • 設(shè)置isa指向的Class
      Class object_setClass(id obj, Class cls)
    • 判斷一個OC對象是否為Class
      BOOL object_isClass(id obj)
    • 判斷一個Class是否為元類
      BOOL class_isMetaClass(Class cls)
    • 獲取父類
      Class class_getSuperclass(Class cls)
  1. 成員變量
    • 獲取一個實例變量信息
      Ivar class_getInstanceVariable(Class cls, const char * name)
    • 拷貝示例變量列表(最后需要調(diào)用free釋放)
      Ivar *class_copyIvarList(Class cls,unsigned int *outCount)
    • 設(shè)置和獲取成員變量的值
      void object_setIvar(id obj, Ivar ivar, id value)
      id object_getIvar(id obj, Ivar ivar)
    • 動態(tài)添加成員變量(已經(jīng)注冊的類不能動態(tài)添加成員變量)
      BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types)
    • 獲取成員變量的相關(guān)信息
      const char *ivar_getName(Ivar v)
      const char *ivar_getTypeEncoding(Ivar v)
  2. 屬性
    • 獲取一個屬性
      objc_property_t _Nullable class_getProperty(Class _Nullable cls, const char * _Nonnull name)
    • 拷貝屬性列表(需要調(diào)用free釋放)
      objc_property_t _Nonnull * _Nullable class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount)
    • 動態(tài)添加屬性
      BOOL class_addProperty(Class _Nullable cls, const char * _Nonnull name, const objc_property_attribute_t * _Nullable attributes, unsigned int attributeCount)
    • 動態(tài)替換屬性
      void class_replaceProperty(Class _Nullable cls, const char * _Nonnull name, const objc_property_attribute_t * _Nullable attributes, unsigned int attributeCount)
    • 獲取屬性的一些信息
      const char * _Nonnull property_getName(objc_property_t _Nonnull property)
      const char * _Nullable property_getAttributes(objc_property_t _Nonnull property)
  3. 方法
    • 獲得一個實例方法檬姥、類方法
      Method _Nullable class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
      Method _Nullable class_getClassMethod(Class _Nullable cls, SEL _Nonnull name)
    • 方法實現(xiàn)相關(guān)操作
      IMP _Nullable class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name)
      IMP _Nonnull method_setImplementation(Method _Nonnull m, IMP _Nonnull imp)
      void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)
    • 拷貝方法列表(需要調(diào)用free函數(shù)釋放)
      Method _Nonnull * _Nullable class_copyMethodList(Class _Nullable cls, unsigned int * _Nullable outCount)
    • 動態(tài)添加方法
      BOOL class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types)
    • 動態(tài)替換方法
      IMP _Nullable class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types)
    • 獲取方法的相關(guān)信息(帶有copy的需要調(diào)用free釋放)
      SEL _Nonnull method_getName(Method _Nonnull m)
      IMP _Nonnull method_getImplementation(Method _Nonnull m)
      const char * _Nullable method_getTypeEncoding(Method _Nonnull m)
      unsigned int method_getNumberOfArguments(Method _Nonnull m)
      char * _Nonnull method_copyReturnType(Method _Nonnull m)
      char * _Nullable method_copyArgumentType(Method _Nonnull m, unsigned int index)
    • 選擇器相關(guān)
      const char * _Nonnull sel_getName(SEL _Nonnull sel)
      SEL _Nonnull sel_registerName(const char * _Nonnull str)
    • 用block作為方法實現(xiàn)
      IMP _Nonnull imp_implementationWithBlock(id _Nonnull block)
      id _Nullable imp_getBlock(IMP _Nonnull anImp)
      BOOL imp_removeBlock(IMP _Nonnull anImp)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曾我,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子健民,更是在濱河造成了極大的恐慌抒巢,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秉犹,死亡現(xiàn)場離奇詭異蛉谜,居然都是意外死亡,警方通過查閱死者的電腦和手機崇堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門型诚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸳劳,你說我怎么就攤上這事狰贯。” “怎么了赏廓?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵涵紊,是天一觀的道長。 經(jīng)常有香客問我幔摸,道長摸柄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任既忆,我火速辦了婚禮驱负,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尿贫。我一直安慰自己电媳,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布庆亡。 她就那樣靜靜地躺著匾乓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪又谋。 梳的紋絲不亂的頭發(fā)上拼缝,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天娱局,我揣著相機與錄音,去河邊找鬼咧七。 笑死衰齐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的继阻。 我是一名探鬼主播耻涛,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瘟檩!你這毒婦竟也來了抹缕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤墨辛,失蹤者是張志新(化名)和其女友劉穎卓研,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體睹簇,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡奏赘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了太惠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片磨淌。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖垛叨,靈堂內(nèi)的尸體忽然破棺而出伦糯,到底是詐尸還是另有隱情,我是刑警寧澤嗽元,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布敛纲,位于F島的核電站,受9級特大地震影響剂癌,放射性物質(zhì)發(fā)生泄漏淤翔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一佩谷、第九天 我趴在偏房一處隱蔽的房頂上張望旁壮。 院中可真熱鬧,春花似錦谐檀、人聲如沸抡谐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽麦撵。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間免胃,已是汗流浹背惩淳。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工奖亚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留杆兵,地道東北人伟骨。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像扼雏,于是被迫代替她去往敵國和親坚嗜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容