开发中常见的错误
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ViewController function]: unrecognized selector sent to instance 0x7fdd10d17e00'复制代码
这代表function 方法没有实现,常见于.h 声明了方法,但是.m没有实现,或者
[self performSelector:NSSelectorFromString(@"function")];复制代码
这种利用字符串生成方法的代码,
unrecognized selector sent to instance 0x7fdd10d17e00'原因是因为methodSignatureForSelector这个方法中,由于没有找到run对应的实现方法,所以返回了一个空的方法签名,最终导致程序报错崩溃 这些代码Xcode都不会抛出错误,OC会提供3次机会来挽救
方法一: 动态解析
声明替补方法
void function(id sf,SEL cd){ NSLog(@"%@",sf); NSLog(@"%@",NSStringFromSelector(cd));}复制代码
进行动态方法解析 利用运行时给对象添加方法
+(BOOL)resolveInstanceMethod:(SEL)sel { if (sel == @selector(function)) { class_addMethod(self, sel, (IMP)function, "v@:"); } return [super resolveInstanceMethod:sel];}复制代码
这样方法的执行被转发到替代方法中
方法二: 快速转发 再本实例找不到方法的实现,可以将消息转发到实现该方法的对象
实现方法的实例
@implementation Function-(void)function{ NSLog(@"do function");}@end复制代码
实现快速消息转发 该方法的返回值就是执行未找到方法的对象
-(id)forwardingTargetForSelector:(SEL)aSelector { Function *fun = [[Function alloc]init]; if ([fun respondsToSelector:aSelector]) { return fun; } return [super forwardingTargetForSelector:aSelector];}复制代码
这样fun 对象就会执行 -(void)function 方法
方法三: 标准消息转发
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ if (aSelector == @selector(function)) { return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } return [super methodSignatureForSelector:aSelector];}-(void)forwardInvocation:(NSInvocation *)anInvocation{ SEL selector = [anInvocation selector]; Function *fun1 = [[Function alloc]init]; Function *fun2 = [[Function alloc]init]; if ([fun1 respondsToSelector:selector]) { [anInvocation invokeWithTarget:fun1]; } if ([fun2 respondsToSelector:selector]) { [anInvocation invokeWithTarget:fun2]; }}复制代码
methodSignatureForSelector:用来生成方法签名,这个签名就是给forwardInvocation:中的参数anInvocation调用的。 方法三中我们自己新建方法签名,在forwardInvocation中用你要转发的那个对象调用这个对应的签名,这样也实现了消息转发。
方法二和方法三都是消息转发,方法二简单快速但是只能将消息转发给一个对象,方法三比较复杂速度慢但是可以将消息转发给多个对象