// Method Swizzling 的最佳實踐
// 下面我們就以替換 viewWillAppear 方法為例談談 Method Swizzling 的最佳實踐,話不多說,直接上代碼:
@interface UIViewController (MRCUMAnalytics) @end @implementation UIViewController (MRCUMAnalytics) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class class = [self class]; SEL originalSelector = @selector(viewWillAppear:); SEL swizzledSelector = @selector(mrc_viewWillAppear:); Method originalMethod = class_getInstanceMethod(class, originalSelector); Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (success) { class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } }); } #pragma mark - Method Swizzling - (void)mrc_viewWillAppear:(BOOL)animated { [self mrc_viewWillAppear:animated]; [MobClick beginLogPageView:NSStringFromClass([self class])]; } @end
- 為什么是在
+load方法中實作 Method Swizzling 的邏輯,而不是其他的什么方法,比如+initialize等; - 為什么 Method Swizzling 的邏輯需要用 dispatch_once 來進行調度;
- 為什么需要呼叫
class_addMethod方法,并且以它的結果為依據分別處理兩種不同的情況,
下面我們就一起來分析下這三個為什么到底是為了什么?
第 1 個為什么:看過我前面文章《Objective-C +load vs +initialize》 的同學應該知道,+load 和 +initialize 是 Objective-C runtime 會自動呼叫的兩個類方法,但是它們被呼叫的時機卻是有差別的,+load 方法是在類被加載的時候呼叫的,而 +initialize 方法是在類或它的子類收到第一條訊息之前被呼叫的,這里所指的訊息包括實體方法和類方法的呼叫,也就是說 +initialize 方法是以懶加載的方式被呼叫的,如果程式一直沒有給某個類或它的子類發送訊息,那么這個類的 +initialize 方法是永遠不會被呼叫的,此外 +load 方法還有一個非常重要的特性,那就是子類、父類和分類中的 +load 方法的實作是被區別對待的,換句話說在 Objective-C runtime 自動呼叫 +load 方法時,分類中的 +load 方法并不會對主類中的 +load 方法造成覆寫,綜上所述,+load 方法是實作 Method Swizzling 邏輯的最佳“場所”,
第 2 個為什么:我們上面提到,+load 方法在類加載的時候會被 runtime 自動呼叫一次,但是它并沒有限制程式員對 +load 方法的手動呼叫,什么?你說不會有程式員這么干?那可說不定,我還見過手動呼叫 viewDidLoad 方法的程式員,就是介么任性,而我們所能夠做的就是盡可能地保證程式能夠在各種情況下正常運行,
第 3 個為什么:我們使用 Method Swizzling 的目的通常都是為了給程式增加功能,而不是完全地替換某個功能,所以我們一般都需要在自定義的實作中呼叫原始的實作,所以這里就會有兩種情況需要我們分別進行處理:
推薦參考鏈接: https://mp.weixin.qq.com/s/n-G9cbjiRwxNzzCO9kOf5w
值得細看一下.非常不錯
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/15114.html
標籤:iOS
上一篇:super performSelector: 解決呼叫父類私有方法的問題
下一篇:Flutter - 生命周期
