2019-11-13 ios消息转发机制

在OC中,函数的执行,本质是消息发送。

所有的函数调用转化为C函数即obj_msgSend(id,sel,param)

不同于其他语言,在对象中声明的方法可以不必非得实现,编译也能通过,虽然最后程序会崩溃。

unrecognized selector sent to instance  xxxxx

当一个实例对象调调用方法时,首先会在自己的类对象的方法列表中查找对应的方法,没找到的话就通过父类继续查找。

只到查找到NSOBject类中,也没有发现相应的方法,此时就会触发消息转发机制。

说白了,消息转发机制就是系统给你拯救程序崩溃的机会,这样的机会一共有三次,如果这三次机会都没有把消息处理掉,程序才会崩溃。

第一次机会:通过NSObeject的实例方法:-(BOOL)resolveInstanceMethod:(SEL)sel

你只有在这个方法中,处理消息并且返回YES,那么消息转发过程就会终止,程序正常运行。处理过程如下:

 NSString *selStr = NSStringFromSelector(sel);

    if([selStr  isEqualToString:@"yourMethodName"]) {

        IMP  imp =class_getMethodImplementation(self,@selector(replaceMethod));//替代实现的方法

        class_addMethod(self, sel, imp,"v@:");//动态添加一个方法,来代替原来方法的实现

        returnYES;

    }else{

        return [super resolveInstanceMethod:sel];

    }

如果这个方法最终返回的是NO,那么第二次机会就登场了:NSObeject的实例方法:-(id)forwardingTargetForSelector:(SEL sel);

这个方法返回的是一个id类型,即任何类型。你可以理解为一个代理对象,当前对象没有实现的方法,交给其他类实现。

- (id)forwardingTargetForSelector:(SEL sel){

     NSString *selStr = NSStringFromSelector(sel);

        if([selStr  isEqualToString:@"yourMethodName"]) {

                    return [DelegateObject new];//在DelegateObject类中实现对应的方法

         }else{

                return nil;

         }

}

如果在这一步还是没有处理,那么就只剩最后一次机会了:NSObeject的实例方法:-(void)forwardInvocation:(NSInvocation *)anInvocation;

    if(anInvocation.selector==@selector(sing)) {

        DelegateObject*delegate =DelegateObject;

        [anInvocation  invokeWithTarget:delegate];//也是交给其他对象处理

    }

在调用这个方法之前还要返回对应方法的编码类型,实现函数-(NSMethodSignature*)methodSignatureForSelector:(SEL)sel;

    if(aSelector ==@selector(yourmethod)) {

        return  [NSMethodSignature signatureWithObjCTypes:"V@:@"];//V代表返回值为void,@代表消息接收对象,:代表选择子,@代表参数

    }

    return [super methodSignatureForSelector:aSelector];

以上就是OC消息转发机制了。虽然有这个机制的存在,但最好还是不要用到这个,养成的良好的编码习惯,在头文件中声明的函数要自己完成实现。

你可能感兴趣的:(2019-11-13 ios消息转发机制)