Objective-C消息機制

在Objective-C中咱們能夠向一個實例發送消息(方法調用),實例收到消息後會進行一些處理。html

一、實例收到消息後,若是能respondsToSelector,那麼就會調用相應的方法。ios

二、若是不能respond通常狀況下會crash。學習

 

 向一個實例發送一個消息後,系統處理的流程:atom

 1. 發送消息如:[self startwork]spa

 2. 系統會check是否能response這個消息code

 3. 若是能response則調用相應方法,不能則拋出異常htm

 

 系統是如何check實例是否能response消息:blog

 一、若是實例自己就有相應的response,那麼就會響應之,ip

 二、若是沒有系統就會發出methodSignatureForSelector消息,尋問它這個消息是否有效?有效就返回對應的方法地址之類的,無效則返回nil。get

重寫methodSignatureForSelector時,需人工讓其返回有效實例並分發給多個響應者。

 三、若是是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消息轉發

相關文章
相關標籤/搜索