理解消息转发机制分为两大阶段:
第一阶段:
先征询接受者所属的类, 看其是否能动态添加方法,以处理当前这个‘未知的选择器’,这个叫做‘动态方法解析’
第二阶段:
涉及‘完整的消息转发机制’, 如果运行期系统已经把第一阶段执行完,那么接受者就无法再以动态新增的方法的手段来响应包含该选择器的消息了,此时,运行期系统会请求接受者以其他手段来处理与消息有关的方法调用,
这个细节分为两步,首先请接受者看看有没有其他对象能处理这条消息,
- 若有,则运行期系统会把消息转给那个对象,消息转发结束,一切如常;
- 若没有,则穷完整的消息转发机制,运行期系统会把消息有关的全部细节都封装到NSInvocation对象中,再给接受者最后一个机会,令其设法解决当前还未处理的这条消息;
// 创建GCMessageForwarding,在 GCMessageForwarding.h写一个放方法但是不去实现```
-(void)lowercasseString;
1 |
|
方法没实现,由NSobject的doesNotRecognizeSelector抛出, 此异常表明:接受者的类型是GCMessageForwarding,而该接受者无法理解该选择器
-[GCMessageForwarding lowercasseString]: unrecognized selector sent to instance 0x1740044d0
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[GCMessageForwarding lowercasseString]: unrecognized selector sent to instance 0x1740044d0’
1 |
|
void messageForwarding() {
NSLog(@”show Test02”);
}
- (BOOL)resolveInstanceMethod:(SEL)sel {
NSString *selString = NSStringFromSelector(sel);
if ([selString isEqualToString:@”lowercasseString”]) {
}class_addMethod(self, sel, (IMP)messageForwarding, "v@:@");
return YES;
}这时就会打印 ```show Test02```
方法 resolveInstanceMethod
也没实现
如果方法 resolveInstanceMethod
也没实现,就会掉用备用方法 forwardingTargetForSelector
,把这条消息转给其他接受者来处理
整个调用流程
lowercasseString(未实现) -> resolveInstanceMethod(未实现) ->forwardingTargetForSelector(未实现) -> resolveInstanceMethod(未实现) -> NSobject的doesNotRecognizeSelector抛出异常