开发中常见的错误
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中用你要转发的那个对象调用这个对应的签名,这样也实现了消息转发。
方法二和方法三都是消息转发,方法二简单快速但是只能将消息转发给一个对象,方法三比较复杂速度慢但是可以将消息转发给多个对象