我們常用的swizzle用法如下:
BOOL simple_Swizzle(Class aClass, SEL originalSel,SEL swizzleSel){
Method originalMethod = class_getInstanceMethod(aClass, originalSel);
Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
method_exchangeImplementations(originalMethod, swizzleMethod);
return YES;
}
BOOL best_Swizzle(Class aClass, SEL originalSel,SEL swizzleSel){
Method originalMethod = class_getInstanceMethod(aClass, originalSel);
Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
BOOL didAddMethod = class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
if (didAddMethod) {
class_replaceMethod(aClass, swizzleSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}else{
method_exchangeImplementations(originalMethod, swizzleMethod);
}
return YES;
}
我們分別用這倆種方法來測試下面的3中情況
swizzle一個父類的方法
我們新建一個Father類
@interface Father : NSObject
- (void)work;
@end
@implementation Father
- (void)work{
NSLog(@"father work");
}
@end
Son類
@interface Son : Father
@end
@implementation Son
@end
simple_Swizzle
+ (void)load{
simple_Swizzle(self,@selector(work), @selector(son_work));
}
- (void)son_work{
NSLog(@"son_category work") ;
[self son_work];
}
調(diào)用[[Father new] work]
報錯
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Father son_work]: unrecognized selector sent to instance 0x60c0000140a0'
分析:
由于class_getInstanceMethod
方法回去父類里面尋找优烧, 最后找到父類的方法债热,因為我們做了交換粱栖,所以父類的方法已經(jīng)被交換son_work
,而父類里面沒有實現(xiàn)son_work
best_Swizzle
由于第二種方法在子類里面add了一個方法澡绩,所以交換正常徐许。
swizzle一個不存的方法
我們將Father
類work
的具體實現(xiàn)去掉佃乘,然后使用上面?zhèn)z個方法來測試swizzle
simple_Swizzle
報錯
'NSInvalidArgumentException', reason: '-[Son work]: unrecognized selector sent to instance 0x60c000006e40'
分析:
由于class_getInstanceMethod
方法會找不到松嘶,返回nil恍箭。所以method_exchangeImplementations
會失敗,保持原樣佛玄。所以最后仍然會找不到方法硼一。
best_Swizzle
會循環(huán)調(diào)用son_work
。
分析:
由于class_getInstanceMethod
方法會找不到梦抢,返回nil般贼。這時add也不可能成功,最后交互也會失敗奥吩,所以最后這種寫法就變成了循環(huán)調(diào)用鸵闪。
- (void)son_work{
NSLog(@"son_category work") ;
[self son_work];
}
swizzle 不同class的倆個方法
如果我們把Father
的work
方法和animal
方法交換店诗,考慮下下面的代碼巩踏。
- (void)animal_wrok{
NSLog(@"animal work");
// 這時如果訪問self 的變量置森, 方法會怎么樣?
}