美文网首页
ios学习之彻底搞清楚消息转发

ios学习之彻底搞清楚消息转发

作者: 北你妹的风 | 来源:发表于2018-03-23 11:59 被阅读9次

    首先要搞清楚一点的是,在OC中方法的调用是向对象发送消息。

    比如:[person    run],就是向person这个对象发送叫做run的消息。因为Objective-C运行时的存在,即使person对应的类中没有run这个方法,在编译期间也不会报错,但程序最终会报错:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person run]: unrecognized selector sent to instance

    本文就从这个异常说起,彻底搞清楚Objective-C的消息转发机制。

    当向一个对象发送某个消息时,程序在运行期间会通过对象所属类的方法列表中去找对应的方法,找到就执行,找不到就从父类中找。如果最后在NSObject中也没有这个方法时,运行时系统会提供3套备选方案进行补救。

    第一种方案:

    + (BOOL)resolveInstanceMethod:(SEL)sel

    + (BOOL)resolveClassMethod:(SEL)sel

    如果是实例方法,则需要实现resolveInstanceMethod:(SEL)sel方法,如果是类方法,实现resolveClassMethod:(SEL)sel即可。

    比如上面Person类中的实例方法run,如果没有实现这个方法,就可以通过实现resolveInstanceMethod:(SEL)sel来进行补救。

    在Person.m文件中添加方法:

    + (BOOL)resolveInstanceMethod:(SEL)sel{

                if(sel==@selector(run)){

                        class_addMethod(self,sel,(IMP)runMethod,"v@:");

                        return YES;

                }

                return [super resolveInstanceMethod :sel];

    }

    void  runMethod(id self,SEL _cmd){

                NSLog(@"重新实现run方法");

    }

    一句话总结这种方案就是:给目标对象动态添加一个方法实现。

    第二种方案:

    实现forwardingTargetForSelector方法。

    还是上面的例子,新建一个类Tiger,在这个类中实现方法run如下:

    -(void) run{

        NSLog("tiger run ");

    }

    在Person.m文件中添加方法:

    -(id)forwardingTargetForSelector:(SEL)sel{

                return [ [Tiger alloc]init];

    }

    一句话总结这种方案,本身类没有实现的方法,可以转给其他类实现。

    第三种方案:

    实现methodSignatureForSelector和forwardInvocation两个方法,第一个方法用于生成签名,第二个方法实际作为转发对象调用方法。

    -(void)forwardInvocation:(NSInvocation*)invocation{

            SEL selector=[invocation selector];

            Tiger *tiger=[[Tiger alloc]init];

             if(tiger respondsToSelector:selector){

                    [invocation  invokeWithTarget:tiger];

            }

    }

    这种方案本质上和第二种方案一样,转发给其他类进行实现。

    相关文章

      网友评论

          本文标题:ios学习之彻底搞清楚消息转发

          本文链接:https://www.haomeiwen.com/subject/lomtcftx.html