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消息转发

posted on 2017-06-20 17:21  Beche  阅读(137)  评论(0编辑  收藏  举报

导航