iOS消息转发机制
在iOS日常开发过程中,当我们所调用的方法不存在时,便会报这样一个异常错误。unrecognized selector sent to instance 0x000f0203ce
这种异常是由于我们没有去实现调用的方法造成的。解决方式也很简单,只要在对应的类或者其父类中添加相应的方法即可。而我们今天要讲的是另外一种解决方式。
iOS的消息转发
我们都知道iOS由于runtime机制的原因是一门动态运行时语言。因此我们可以在运行期间增加方法。
消息的动态转发机制分为三大步:
第一步:当我们所调用的方法不存在时,首先检测是否可以通过runtime动态添加方法,因此会先去调用以下方法。
+ (BOOL)resolveInstanceMethod:(SEL)sel;//通过对象调用则触发该方法
+ (BOOL)resolveClassMethod:(SEL)sel;//通过类方法调用则触发该方法
通过重写resolveInstanceMethod方法,使用class_addMethod动态添加方法
+(BOOL)resolveInstanceMethod:(SEL)sel {
NSString *methodStr = NSStringFromSelector(sel);
if ([methodStr isEqualToString:@"test:"]) {
IMP timer = [[self class] instanceMethodForSelector:@selector(timerStart)];
class_addMethod(self, sel, timer, "v@i");
return YES;
}
return NO;
}
第二步:如果未能通过runtime动态添加方法,则会去询问是否可以通过其它类来解决该问题。询问时会自动调用以下方法。
- (id)forwardingTargetForSelector:(SEL)aSelector;
通过重写forwardingTargetForSelector方法,当test:方法在本类无法处理时,可交给BaseViewController类来进行处理。
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSString *seletorString = NSStringFromSelector(aSelector);
if ([@"test:" isEqualToString:seletorString]) {
BaseViewController *s = [[BaseViewController alloc] init];
return s;
}
return [super forwardingTargetForSelector:aSelector];
}