乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      使用objc runtime實現(xiàn)iOS綠色的懶加載

       路人甲Java 2022-01-11

      使用objc runtime實現(xiàn)懶加載

      地址:AutoPropertyCocoa

      本文所指懶加載形式如下

      - (id)lazyloadProperty{
      
          if(_lazyloadProperty == nil){
          
              _lazyloadProperty = [XClass ...];
          }
          return _lazyloadProperty;
      }

      一般使用宏定義可以輕松完成。但是沒有一致性,移植差。

      利用objc runtime的動態(tài)性實現(xiàn)懶加載可以實現(xiàn)即可增加又可刪除功能,也可以避免污染類型。該三方彌補了目前沒有閉環(huán)實現(xiàn)懶加載三方的空缺。

       

      主要實現(xiàn)內(nèi)容:

      1. 實例或者類的懶加載
      2. 如果是實例對象則鉤住并修改類型將其子類化
      3. 對該類型進行method swizzling
      4. 如果現(xiàn)在進行解綁,則判斷是否是自己實現(xiàn)的方法.如果是自己實現(xiàn)的方法->5,否則->6
      5. 調(diào)用method swizzling還原
      6. 刪除這個類型的這個方法

      難點:

      自己實現(xiàn)method swizzling

      1.  重新實現(xiàn)objc1時代的方法class_removeMethods
      2.  鉤住運行時中的runtimelock,實現(xiàn)修改類型數(shù)據(jù)時的安全性

      我們再實現(xiàn)method swizzling時的兩個API

      OBJC_EXPORT IMP _Nullable
      class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, 
                          const char * _Nullable types) 
          OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
      
      OBJC_EXPORT void
      method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) 
          OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

      不管使用哪種,如果這個類型沒有實現(xiàn)該方法而是父類實現(xiàn)的話,就需要動態(tài)增加一個方法。動態(tài)增加的方法在Objc1時代,是可以通過下列方法刪除的:

      OBJC_EXPORT void
      class_removeMethods(Class _Nullable, struct objc_method_list * _Nonnull)
          OBJC2_UNAVAILABLE;

      Objc2時代之后runtime被重寫后沒有該方法了,并且新的runtime的類結(jié)構(gòu)看起來就沒打算讓開發(fā)者刪除方法,所以這里將過程記下。

      首先看類讀寫器的結(jié)構(gòu)class_rw_t

      struct class_rw_t {
          // Be warned that Symbolication knows the layout of this structure.
          uint32_t flags;
          uint32_t version;
      
          const class_ro_t *ro;
      
          method_array_t methods;//刪除這里的一個方法
          property_array_t properties;
          protocol_array_t protocols;
      
          Class firstSubclass;
          Class nextSiblingClass;
      
          char *demangledName;
      
      #if SUPPORT_INDEXED_ISA
          uint32_t index;
      #endif
      };

      method_array_t繼承于list_array_tt<method_t, method_list_t>,它是數(shù)組結(jié)構(gòu)。存儲的內(nèi)容是method_list_t.

      method_list_t又繼承于entsize_list_tt<method_t, method_list_t, 0x3>,他也是數(shù)組結(jié)構(gòu)。

      整個method_array_t結(jié)構(gòu)是二維數(shù)組。每次刪掉一個method_t需要用新method_list_t替換原對象。

       

      然后是線程安全的問題,需要獲取到蘋果在操作類型的時候使用的讀寫鎖(pthread_rw_lock_t runtimelock)。沒有這把鎖任何對runtime的修改都是不可靠的。

      最終采取的方式是:劫持暴露了符號的系統(tǒng)函數(shù)然后阻塞線程

       

      劫持系統(tǒng)C函數(shù)使用的是臉書的魚鉤,這個鉤子在macOS其實也是可以正常工作的。

      剩下的就是尋找合適的函數(shù)了,這函數(shù)要滿足兩個條件:

      1. 該函數(shù)在符號表中存在
      2. 函數(shù)內(nèi)部在lock runtimelock之后存在滿足條件1的第二個函數(shù)

      找了半天發(fā)現(xiàn)最合適的只有objc_allocateProtocol()了,objc_allocateProtocol內(nèi)部會調(diào)用calloc(),所以第二個被劫持函數(shù)就是calloc。為了減小calloc的開銷,需要稍微做一些工作。

      1. 對每次調(diào)用進行比較線程ID的操作顯然比暴力阻塞線程好。
      2. 減小劫持后的calloc的調(diào)用棧。

      雖然不是什么吸引人的UI框架還是希望大家點個贊吧。另外,有成都的公司招iOS嗎

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多