当用Method Swizzling替换子类中未重写的父类方法实现时,class_getInstanceMethod会获取到子类没有重写的父类方法的Method,这个Method对应的是父类中的方法,用这个Method调用method_exchangeImplementations实现Method Swizzling之后就会交换父类Method和子类Method的实现。然后在基类对象上调用被交换的方法时,如果该方法调用了自身就会引起unrecognized selector异常。
提问后追加:1. 我知道unrecognized selector异常出现的原因;2.“这种情况”指的是子类没有重写父类的方法,但是代码中又需要针对这个特定子类及其派生类重写方法实现的情况。
具体情景可以参照:需要在UITableViewCell类及其子类上重写NSObject实现的方法setValue:forKeyPath:
,而又不影响UITableViewCell的基类的方法调用结果。
问:
在这种情况下,如何“更优美”地达到重写不能修改源码的特定方法的目的呢?
示例代码如下:
#类声明
@interface BaseClass : NSObject
- (void)baseVersionMethod;
@end
@interface SubClass : BaseClass
@end
@interface SubClass (MySubClass)
- (void)myMethod;
@end
#类定义
@implementation BaseClass
- (void)baseVersionMethod {
NSLog(@"baseVersionMethod has been called.");
}
@end
@implementation SubClass
@end
@implementation SubClass (MySubClass)
- (void)myMethod {
NSLog(@"myMethod");
[self myMethod];
}
+ (void)load {
Method oriM = class_getInstanceMethod(SubClass.class, @selector(baseVersionMethod));
Method newM = class_getInstanceMethod(SubClass.class, @selector(myMethod));
method_exchangeImplementations(oriM, newM);
}
@end
#调用交换后的方法
int main(int argc, char * argv[]) {
BaseClass *obj = [[BaseClass alloc] init];
[obj baseVersionMethod];//抛出unrecognized selector异常
}
父类没有实现子类的方法,当然会抛异常啊。
可以在父类的类别里实现