zoukankan      html  css  js  c++  java
  • Objective-C消息机制

    在Objective-C中我们可以向一个实例发送消息(方法调用),实例收到消息后会进行一些处理。

    1、实例收到消息后,如果能respondsToSelector,那么就会调用相应的方法。

    2、如果不能respond一般情况下会crash。

     向一个实例发送一个消息后,系统处理的流程:

     1. 发送消息如:[self startwork]

     2. 系统会check是否能response这个消息

     3. 如果能response则调用相应方法,不能则抛出异常

     系统是如何check实例是否能response消息:

     1、如果实例本身就有相应的response,那么就会响应之,

     2、如果没有系统就会发出methodSignatureForSelector消息,寻问它这个消息是否有效?有效就返回对应的方法地址之类的,无效则返回nil。

    重写methodSignatureForSelector时,需人工让其返回有效实例并分发给多个响应者。

     3、如果是nil,Runtime则会发出-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果不是nil接着发送forwardInvocation消息。

    @property (nonatomic, assign) BOOL silentWhenEmpty; // 找不到方法实现时是否抛错,  默认抛错。
    @property (readonly, nonatomic) NSArray *plugins;
    
    // 判断super、plugin是否response
    - (BOOL)respondsToSelector:(SEL)selector
    {
        if ([super respondsToSelector:selector])
            return YES;
    
        for (id plugin in _plugins){
            if (plugin && [plugin respondsToSelector:selector])
                return YES;
        }
        return NO;
    }
    
    // respondsToSelector返回No,进入该方法
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
    {
        NSMethodSignature *signature = [super methodSignatureForSelector:selector];
        if (signature)
            return signature;
    
        if (self.silentWhenEmpty && _plugins.count == 0){
            // 任意指定一个method signature
            return [self methodSignatureForSelector:@selector(description)];
        }
    
        for (id plugin in _plugins){
            if (!plugin)
                continue;
    
            signature = [plugin methodSignatureForSelector:selector];
            if (signature)
                break;
        }
    
        return signature;
    }
    
    // 假如methodSignatureForSelector返回不是nil,进入该方法
    - (void)forwardInvocation:(NSInvocation *)invocation
    {
        SEL selector = [invocation selector];
        BOOL responded = NO;
        BOOL swallowed = NO;
        for (id plugin in _plugins){
            if (plugin && [plugin respondsToSelector:selector]){
                [invocation invokeWithTarget:plugin];
                [invocation getReturnValue:(void *)&swallowed];
                responded = YES;
                if (swallowed){
                    break;
                }
            }
        }
    
        if (!responded && !self.silentWhenEmpty) // 没响应,允许报错
            [self doesNotRecognizeSelector:selector];
    }

    看更多内容,打开轻松学习之 Objective-C消息转发

  • 相关阅读:
    img标签中alt属性与title属性在seo的作用-摘自网友
    C# 从补码中获取有符号数的实际数值
    you need to load the kernel first
    桌面远程访问
    供应商通过向日葵访问公司外网办公电脑,通过办公电脑访问内网内生产用电脑
    配置交换机口可以上外网
    抠图和不失真的改变图形大小
    用机房现有双网口电脑添加监控
    服务器配置IP
    在DELL服务器上安装windows2012 r2服务器系统
  • 原文地址:https://www.cnblogs.com/zhouyi-ios/p/7055265.html
Copyright © 2011-2022 走看看