面試題:在程序中方法實現只執行一次,利用runtime方法交換重寫viewwillappear。
1、新建分類
#import "UIViewController+swizzling.h"
#import <objc/runtime.h>
@implementation UIViewController (swizzling)
//load方法會在類第一次加載的時候被調用
//調用的時間比較靠前,適合在這個方法裏做方法交換
+ (void)load{
//方法交換應該被保證,在程序中只會執行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"once load");
//獲得viewController的生命週期方法的selector
SEL systemSel = @selector(viewWillAppear:);
//自己實現的將要被交換的方法的selector
SEL swizzSel = @selector(swiz_viewWillAppear:);
//兩個方法的Method
Method systemMethod = class_getInstanceMethod([self class], systemSel);
Method swizzMethod = class_getInstanceMethod([self class], swizzSel);
//首先動態添加方法,實現是被交換的方法,返回值表示添加成功還是失敗
BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));
if (isAdd) {
//如果成功,說明類中不存在這個方法的實現
//將被交換方法的實現替換到這個並不存在的實現
class_replaceMethod(self, swizzSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
}else{
//否則,交換兩個方法的實現
method_exchangeImplementations(systemMethod, swizzMethod);
}
});
}
- (void)swiz_viewWillAppear:(BOOL)animated{
//這時候調用自己,看起來像是死循環
//但是其實自己的實現已經被替換了
[self swiz_viewWillAppear:animated];
NSLog(@"swap");
}
2、測試,首先輸出swizzle 然後輸出viewWillAppear
在一個自己定義的viewController中重寫viewWillAppear
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"viewWillAppear");
}