美文网首页
消息转发流程

消息转发流程

作者: wpf_register | 来源:发表于2021-03-08 16:02 被阅读0次

    iOS开发过程中我们经常会碰到这样的报错:
    unrecognized selector sent to instance **,我们调用了一个不存在的方法。
    用OC消息机制来说就是:消息的接收者不过到对应的selector,这样就启动了消息转发机制。

    抛出异常之前消息转发过程中的步骤:

    1.(动态方法解析)询问是否有动态添加方法来进行处理
     +(BOOL)resolveInstanceMethod:(SEL)sel
    
    void speak(id self, SEL _cmd,NSSting *msg){
        NSLog(@"Now I can speak.%@",msg);
    }
    
    + (BOOL)resolveInstanceMethod:(SEL)sel {
        
        NSLog(@"resolveInstanceMethod:  %@", NSStringFromSelector(sel));
        if (sel == @selector(speak)) {
           
          #动态添加方法
           return   class_addMethod([self class], sel, (IMP)speak, "V@:@");
       
        }
        return [super resolveInstanceMethod:sel];
    }
    

    class_addMethod方法动态添加了一个speak的实现方法来解决掉这条未知的消息,
    此时消息转发过程提前结束。

    2.(快速转发)询问是否有别的类实现该方法
    - (id)forwardingTargetForSelector:(SEL)aSelector
    
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        NSLog(@"forwardingTargetForSelector:  %@", NSStringFromSelector(aSelector));
        Bird *bird = [[Bird alloc] init];
        if ([bird respondsToSelector: aSelector]) {
            return bird;
        }
        return [super forwardingTargetForSelector: aSelector];
    }
    // Bird.m
    - (void)fly {
        NSLog(@"I am a bird, I can fly.");
    }
    

    其它类能实现相应方法,则返回相应实例响应对应方法,消息转发提前结束。

    3. 调用签名方法并转发
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    

    调用forwardInvocation方法前先调用方法签名

    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        NSLog(@"method signature for selector: %@", NSStringFromSelector(aSelector));
        if (aSelector == @selector(code)) {
            return [NSMethodSignature signatureWithObjCTypes:"V@:@"];
        }
        return [super methodSignatureForSelector:aSelector];
    }
    
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
        NSLog(@"forwardInvocation: %@", NSStringFromSelector([anInvocation selector]));
        if ([anInvocation selector] == @selector(code)) {
           
            Monkey *monkey = [[Monkey alloc] init];
            [anInvocation invokeWithTarget:monkey];
      
      } else{
    
           [supre  forwardInvocation:anInvocation];
        }  
    }
    
    

    signatureWithObjCTypes
    第一个表示返回值类型,例如:@为id类型,v为void类型
    第二个表示函数调用者类型self,即为id类型。一般表示为@
    第三个表示SEL方法选择器,一般表示为:冒号。
    第四个表示参数类型。例如:i表示int类型

    #获取类型编码字符串
    NSLog(@"id 类型的编码是:%s",@encode(id));      //@
    
    4. 最后都不能处理,进入Crash
    - (void)doesNotRecognizeSelector:(SEL)aSelector{
          NSLog(@"找不到方法");
    }
    

    相关文章

      网友评论

          本文标题:消息转发流程

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