国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

使用objc runtime實現iOS閉環的懶加載功能

2020-07-26 02:19:45
字體:
來源:轉載
供稿:網友

使用objc runtime實現懶加載

地址:AutoPropertyCocoa

懶加載形式如下

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

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

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

主要流程:

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

難點:

自己實現method swizzling

  1.  重新實現objc1時代的方法class_removeMethods
  2.  鉤住運行時中的runtimelock,實現修改類型數據時的安全性

我們再實現method swizzling時的兩個API

OBJC_EXPORT IMP _Nullableclass_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 voidmethod_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)   OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

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

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

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

首先看類讀寫器的結構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>,它是數組結構。存儲的內容是method_list_t.

method_list_t又繼承于entsize_list_tt<method_t, method_list_t, 0x3>,他也是數組結構。

整個method_array_t結構是二維數組。每次刪掉一個method_t需要用新method_list_t替換原對象。

 

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

最終采取的方式是:劫持暴露了符號的系統函數然后阻塞線程

 

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

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

  1. 該函數在符號表中存在
  2. 函數內部在lock runtimelock之后存在滿足條件1的第二個函數

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

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

總結

以上所述是小編給大家介紹的使用objc runtime實現iOS閉環的懶加載功能,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广东省| 浦北县| 富阳市| 肥城市| 斗六市| 江华| 开阳县| 濮阳市| 万荣县| 万安县| 郎溪县| 乃东县| 咸丰县| 金寨县| 遂昌县| 句容市| 千阳县| 嘉祥县| 樟树市| 仪陇县| 鹤峰县| 清镇市| 安西县| 友谊县| 红河县| 错那县| 乐至县| 温泉县| 视频| 望奎县| 丰镇市| 光泽县| 盐山县| 城口县| 仁化县| 二连浩特市| 漳平市| 新巴尔虎左旗| 如东县| 长乐市| 哈巴河县|