????????當向Objc對象發送消息時,如果找到對象對應的方法,就會進入消息轉發流程,給開發者提供一些最后的機會處理消息無法發送問題,以免出現程序崩潰。
? ? ??
????????1. 回調對象的resolveInstanceMethod方法,在這個方法中,允許開發者在運行時為指定對象添加一個方法,然后返回YES。
// 重寫 resolveInstanceMethod: 嘗試添加對象方法實現
+ (BOOL)resolveInstanceMethod:(SEL)sel{if (sel == @selector(way)) {class_addMethod([self class],sel,class_getMethodImplementation([self class], @selector(method)), "123");//使用class_addMethod動態添加方法method}return YES;
}
? ? ? 2. 若用戶未重寫resolveInstanceMethod, 或者未能在重寫方法中正確處理,則將會調用對象的forwardingtargetForSelector方法,該方法允許用戶將消息轉發到一個可以接收該消息的其他對象。
//嘗試將消息轉發到一個新對象
if (aSelector == @selector(way)) {Friends *friends = [[Friends alloc]init];return friends;//返回friends對象,讓friends對象接受這個消息}return [super forwardingTargetForSelector:aSelector];
}
? ? ? ? 3. 若上一步仍然未能正確處理, 對象的methodsignnatureForSelector?&?forwardInvocation方法將會被調用,允許用戶在拋異常前進行最后的挽救。
//最后一次嘗試對消息進行轉發,可嘗試多個轉發對象
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{if (aSelector == @selector(way)) {return [NSMethodSignature methodSignatureForSelector:@selector(way)];}return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{SEL sel = anInvocation.selector;Friends *f = [[Friends alloc] init];if([f respondsToSelector:sel]) { // 判斷 Person 對象方法是否可以響應 sel[anInvocation invokeWithTarget:f]; // 若可以響應,則將消息轉發給其他對象處理} else {[self doesNotRecognizeSelector:sel]; // 若仍然無法響應,則報錯:找不到響應方法}
}
????????4. 若消息仍未能正確處理,系統則會拋出unrecognized selector 異常