// Method Swizzling 的最佳實踐 // 下麵我們就以替換 viewWillAppear 方法為例談談 Method Swizzling 的最佳實踐,話不多說,直接上代碼: 下麵我們就一起來分析下這三個為什麼到底是為了什麼? 第 1 個為什麼:看過我前面文章《Objective-C ...
// 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
值得細看一下.非常不錯