真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

iOS開發(fā)之MethodSwizzling深入淺出



創(chuàng)新互聯(lián)建站于2013年創(chuàng)立,先為墾利等服務(wù)建站,墾利等地企業(yè),進行企業(yè)商務(wù)咨詢服務(wù)。為墾利企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

iOS開發(fā)之 Method Swizzling 深入淺出

只要善用Google,網(wǎng)上有很多關(guān)于Method Swizzling的Demo,在這里我就不打算貼代碼了,主要介紹下概念,原理,注意事項等等。

開發(fā)需求

如果產(chǎn)品經(jīng)理突然說:"在所有頁面添加統(tǒng)計功能,也就是用戶進入這個頁面就統(tǒng)計一次"。我們會想到下面的一些方法:

  • 手動添加

直接簡單粗暴的在每個控制器中加入統(tǒng)計,復(fù)制、粘貼、復(fù)制、粘貼...
上面這種方法太Low了,消耗時間而且以后非常難以維護,會讓后面的開發(fā)人員罵死的。

  • 繼承

我們可以使用繼承的方式來解決這個問題。創(chuàng)建一個基類,在這個基類中添加統(tǒng)計方法,其他類都繼承自這個基類。

然而,這種方式修改還是很大,而且定制性很差。以后有新人加入之后,都要囑咐其繼承自這個基類,所以這種方式并不可取。

  • Category

我們可以為UIViewController建一個Category,然后在所有控制器中引入這個Category。當(dāng)然我們也可以添加一個PCH文件,然后將這個Category添加到PCH文件中。

  • Method Swizzling

我們可以使用蘋果的“黑魔法”Method Swizzling,Method Swizzling本質(zhì)上就是對IMPSEL進行交換。

先了解幾個概念

Selectors, Methods, & Implementations

Objective-C的運行時中,selectors, methods, implementations 指代了不同概念,然而我們通常會說在消息發(fā)送過程中,這三個概念是可以相互轉(zhuǎn)換的。 下面是蘋果 Objective-C Runtime Reference中的描述:

  • Selector(typedef struct objc_selector *SEL):在運行時 Selectors 用來代表一個方法的名字。Selector是一個在運行時被注冊(或映射)的C類型字符串。Selector由編譯器產(chǎn)生并且在當(dāng)類被加載進內(nèi)存時由運行時自動進行名字和實現(xiàn)的映射。

  • Method(typedef struct objc_method *Method):方法是一個不透明的用來代表一個方法的定義的類型。

  • Implementation(typedef id (*IMP)(id, SEL,...)):這個數(shù)據(jù)類型指向一個方法的實現(xiàn)的最開始的地方。該方法為當(dāng)前CPU架構(gòu)使用標(biāo)準(zhǔn)的C方法調(diào)用來實現(xiàn)。該方法的第一個參數(shù)指向調(diào)用方法的自身(即內(nèi)存中類的實例對象,若是調(diào)用類方法,該指針則是指向元類對象(metaclass)。第二個參數(shù)是這個方法的名字selector,該方法的真正參數(shù)緊隨其后。

理解 selector, method, implementation 這三個概念之間關(guān)系的最好方式是:在運行時,類(Class)維護了一個消息分發(fā)列表來解決消息的正確發(fā)送。每一個消息列表的入口是一個方法(Method),這個方法映射了一對鍵值對,其中鍵值是這個方法的名字 selector(SEL),值是指向這個方法實現(xiàn)的函數(shù)指針 implementation(IMP)。 Method swizzling 修改了類的消息分發(fā)列表使得已經(jīng)存在的 selector 映射了另一個實現(xiàn) implementation,同時重命名了原生方法的實現(xiàn)為一個新的 selector。

Method Swizzling原理

Method Swizzing是發(fā)生在運行時的,主要用于在運行時將兩個Method進行交換,我們可以將Method Swizzling代碼寫到任何地方,但是只有在這段Method Swilzzling代碼執(zhí)行完畢之后互換才起作用。

iOS開發(fā)之 Method Swizzling 深入淺出

iOS開發(fā)之 Method Swizzling 深入淺出

Method Swizzling 使用注意

類簇設(shè)計模式

在iOS中NSNumber、NSArray、NSDictionary等這些類都是類簇(Class Clusters),一個NSArray的實現(xiàn)可能由多個類組成。
所以如果想對NSArray進行Swizzling,必須獲取到其“真身”進行Swizzling,直接對NSArray進行操作是無效的。

下面列舉了NSArray和NSDictionary本類的類名,可以通過Runtime函數(shù)取出本類。

類名真身
NSArray __NSArrayI
NSMutableArray __NSArrayM
NSDictionary __NSDictionaryI
NSMutableDictionary __NSDictionaryM

注意要點

  • Swizzling應(yīng)該總在+load中執(zhí)行
  • Swizzling應(yīng)該總是在dispatch_once中執(zhí)行
  • Swizzling在+load中執(zhí)行時,不要調(diào)用[super load]。如果多次調(diào)用了[super load],可能會出現(xiàn)“Swizzle無效”的假象,原理見下圖:

iOS開發(fā)之 Method Swizzling 深入淺出

Swift 自定義類中使用 Method Swizzling

要在 Swift 自定義類中使用 Method Swizzling 有兩個必要條件:

  • 包含 Swizzle 方法的類需要繼承自 NSObject
  • 需要 Swizzle 的方法必須有動態(tài)屬性(dynamic attribute)

注:對于 Swift 的自定義類,因為默認(rèn)并沒有使用 Objective-C 運行時,因此也沒有動態(tài)派發(fā)的方法列表,所以如果要 Swizzle 的是 Swift 類型的方法的話,是需要將原方法和替換方法都加上 dynamic 標(biāo)記,以指明它們需要使用動態(tài)派發(fā)機制。當(dāng)然類也要繼承自 NSObject。

再注:下面這個例子使用了 Objective-C 的動態(tài)派發(fā),對于 NSObject 的子類(UIViewController)是可以直接使用的,并不是 Swift 中自定義的類,因此沒有加 dynamic 標(biāo)記也是可以的。

Method Swizzling 中 Objective-C 與 Swift 的異同

區(qū)別Objective-CSwift
Runtime 頭文件 #import <objc/runtime.h> 不需要
Swizzling 調(diào)用處 load 方法 initialize 方法

注:load 方法只在 Objective-C 里有,而且不能在 Swift 里重載,不管怎么試都會報編譯錯誤。接下來執(zhí)行 Swizzle 最好的地方就是 initialize了,這是調(diào)用第一個方法前的地方。

因為 Swizzling 會改變?nèi)譅顟B(tài),所以我們需要在運行時采取一些預(yù)防措施。GCD 的dispatch_once 可以保證操作的原子性,確保代碼只被執(zhí)行一次,不管有多少個線程。

Method Swizzling 實際應(yīng)用

APM(應(yīng)用性能管理)

網(wǎng)絡(luò)監(jiān)控的原理,應(yīng)該就是hook NSURLConnection , NSURLSession。崩潰收集的原理,應(yīng)該就是hook NSException。

  • https://newrelic.com/ 國外行業(yè)老大
  • http://www.tingyun.com/ 國內(nèi)聽云
  • http://www.oneapm.com/ 國內(nèi)OneAPM
  • http://apm.netease.com/ 國內(nèi)網(wǎng)易

國外資料


新聞名稱:iOS開發(fā)之MethodSwizzling深入淺出
分享URL:http://weahome.cn/article/jggjoh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部