在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消息轉發