Method Swizzling
//
// UIViewController+Tracking.m
// tesssss
//
// Created by iOS on 23/11/17.
// Copyright ? 2017年 iOS. All rights reserved.
//
#import "UIViewController+Tracking.h"
#import <objc/runtime.h>
@implementation UIViewController (Tracking)
// 放在load方法中,當(dāng)類被加載之后就執(zhí)行以下方法。
+ (void)load {
// 防止手動(dòng)調(diào)用 class 方法,保證替換方法只執(zhí)行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(ICE_viewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
/*
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp,
const char * _Nullable types)
* Class cls cls 參數(shù)表示需要添加新方法的類。
* SEL name name 參數(shù)表示 selector 的方法名稱,可以根據(jù)喜好自己進(jìn)行命名。
* IMP imp imp 即 implementation ,表示由編譯器生成的、指向?qū)崿F(xiàn)方法的指針。也就是說,這個(gè)指針指向的方法就是我們要添加的方法。
* const char *types 最后一個(gè)參數(shù) *types 表示我們要添加的方法的返回值和參數(shù)。
如果發(fā)現(xiàn)方法已經(jīng)存在,會(huì)失敗返回,也可以用來做檢查是否已經(jīng)添加過方法了,我們這里是為了避免源方法沒有實(shí)現(xiàn)的情況;
如果方法沒有存在,我們則先嘗試添加被替換的方法的實(shí)現(xiàn)
*/
BOOL didAddMethod = class_addMethod(
class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)
);
/*
判斷class_addMethod是否已經(jīng)添加成功了
YES 則說明被替換方法不存在.也就是被替換的方法沒有被實(shí)現(xiàn),我們需要先把這個(gè)方法實(shí)現(xiàn),然后再執(zhí)行我們想要的效果,用我們自定義的方法去替換被替換的方法. 這里使用到的是class_replaceMethod這個(gè)方法. class_replaceMethod本身會(huì)嘗試調(diào)用class_addMethod和method_setImplementation,所以直接調(diào)用class_replaceMethod就可以了)
NO 則說明被替換方法已經(jīng)存在.直接將兩個(gè)方法的實(shí)現(xiàn)交換即
*/
if (didAddMethod) {
class_replaceMethod(
class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod)
);
}
else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)ICE_viewWillAppear:(BOOL)animated {
[self ICE_viewWillAppear:animated];
NSLog(@"ICEviewWillAppear:%@",self);
}
@end
//如果替換的是類方法
Class classB = Object_getClass ((id) self);
SEL originalSelector = @selector (想要替換的類方法);
SEL swizzledSelector = @selector (替換的新方法名) ;
Method originalMethod = class_getClassMethod (classB, originalSelector);
Method swizzlingMethod = class_getClassMethod (classB, swizzledSelector);
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。