今天就跟大家聊聊有關(guān)使用objc runtime實(shí)現(xiàn)iOS怎么閉環(huán)的懶加載功能,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
懶加載形式如下
- (id)lazyloadProperty{ if(_lazyloadProperty == nil){ _lazyloadProperty = [XClass ...]; } return _lazyloadProperty; }
一般使用宏定義可以輕松完成。但是沒有一致性,移植差。
利用objc runtime的動(dòng)態(tài)性實(shí)現(xiàn)懶加載可以實(shí)現(xiàn)即可增加又可刪除功能,也可以避免污染類型。該三方彌補(bǔ)了目前沒有閉環(huán)實(shí)現(xiàn)懶加載三方的空缺。
主要流程:
實(shí)例或者類的懶加載
如果是實(shí)例對(duì)象則鉤住并修改類型將其子類化
對(duì)該類型進(jìn)行method swizzling
如果現(xiàn)在進(jìn)行解綁,則判斷是否是自己實(shí)現(xiàn)的方法.如果是自己實(shí)現(xiàn)的方法->5,否則->6
調(diào)用method swizzling還原
刪除這個(gè)類型的這個(gè)方法
難點(diǎn):
自己實(shí)現(xiàn)method swizzling
重新實(shí)現(xiàn)objc1時(shí)代的方法class_removeMethods
鉤住運(yùn)行時(shí)中的runtimelock,實(shí)現(xiàn)修改類型數(shù)據(jù)時(shí)的安全性
我們?cè)賹?shí)現(xiàn)method swizzling時(shí)的兩個(gè)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);
不管使用哪種,如果這個(gè)類型沒有實(shí)現(xiàn)該方法而是父類實(shí)現(xiàn)的話,就需要?jiǎng)討B(tài)增加一個(gè)方法。動(dòng)態(tài)增加的方法在Objc1時(shí)代,是可以通過下列方法刪除的:
OBJC_EXPORT void class_removeMethods(Class _Nullable, struct objc_method_list * _Nonnull) OBJC2_UNAVAILABLE;
Objc2時(shí)代之后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;//刪除這里的一個(gè)方法 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)。存儲(chǔ)的內(nèi)容是method_list_t.
method_list_t又繼承于entsize_list_tt<method_t, method_list_t, 0x3>
,他也是數(shù)組結(jié)構(gòu)。
整個(gè)method_array_t結(jié)構(gòu)是二維數(shù)組。每次刪掉一個(gè)method_t需要用新method_list_t替換原對(duì)象。
然后是線程安全的問題,需要獲取到蘋果在操作類型的時(shí)候使用的讀寫鎖(pthread_rw_lock_t runtimelock)。沒有這把鎖任何對(duì)runtime的修改都是不可靠的。
最終采取的方式是:劫持暴露了符號(hào)的系統(tǒng)函數(shù)然后阻塞線程
劫持系統(tǒng)C函數(shù)使用的是臉書的魚鉤,這個(gè)鉤子在macOS其實(shí)也是可以正常工作的。
剩下的就是尋找合適的函數(shù)了,這函數(shù)要滿足兩個(gè)條件:
該函數(shù)在符號(hào)表中存在
函數(shù)內(nèi)部在lock runtimelock之后存在滿足條件1的第二個(gè)函數(shù)
找了半天發(fā)現(xiàn)最合適的只有objc_allocateProtocol()了,objc_allocateProtocol內(nèi)部會(huì)調(diào)用calloc(),所以第二個(gè)被劫持函數(shù)就是calloc。為了減小calloc的開銷,需要稍微做一些工作。
對(duì)每次調(diào)用進(jìn)行比較線程ID的操作顯然比暴力阻塞線程好。
減小劫持后的calloc的調(diào)用棧。
看完上述內(nèi)容,你們對(duì)使用objc runtime實(shí)現(xiàn)iOS怎么閉環(huán)的懶加載功能有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道,感謝大家的支持。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站chinadenli.net,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
文章題目:使用objcruntime實(shí)現(xiàn)iOS怎么閉環(huán)的懶加載功能-創(chuàng)新互聯(lián)
文章起源:http://chinadenli.net/article18/ejedp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供手機(jī)網(wǎng)站建設(shè)、外貿(mào)建站、微信公眾號(hào)、動(dòng)態(tài)網(wǎng)站、網(wǎng)站導(dǎo)航、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容
營(yíng)銷型網(wǎng)站建設(shè)知識(shí)