消息转发是Objective-C运行时的一个重要特性,具体表现是当调用一个不存在的方法时,并不会立马Crash,Runtime会有三次挽救的机会(准确的说是1次动态方法解析 + 1次快速消息转发 + 1次完整消息转发;)
调用阶段调用方法备注
----------------------------------------------------------------------------------------------------
动态方法解析
+resolveInstanceMethod:(实例方法)
+resolveClassMethod:(类方法)
这里可以动态添加方法
----------------------------------------------------------------------------------------------------
快速消息转发(也叫备援接收者)
-forwardingTargetForSelector:可以在此将消息转发到指定对象,触发新的消息传递
----------------------------------------------------------------------------------------------------
完整消息转发
-methodSignatureForSelector:
-forwardInvocation:
获取签名,并根据方法签名包装成的Invocation,对方法进行处理
----------------------------------------------------------------------------------------------------
消息处理失败
-doesNotRecognizeSelector:抛出异常
接上面,对于调用方法:
[mySon performSelector:@selector(somethingWrong)];
这是一个没有实现的方法,最终会进入消息转发阶段,那么其完整的执行流程如下:
objc_msgSend.png
到此为止已经梳理完了Objective-C中完整的方法调用过程。细心的你可能会发现
- (id)forwardingTargetForSelector:(SEL)aSelector;- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector;- (void)forwardInvocation:(NSInvocation*)anInvocation;- (void)doesNotRecognizeSelector:(SEL)aSelector;
这几个方法都是实例方法,那是否意味着消息转发只针对实例方法有效呢?答案是否定的!前面基本概念的介绍中提到,Classs的isa指针指向的是它的Meta Class,那么意味着一个Class的类方法会加入到它的Meta Class对应的methodLists中,所以你只需要在类中重写下面的类方法,同样可以实现对未知类方法的消息转发。
+ (id)forwardingTargetForSelector:(SEL)aSelector;+ (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector;+ (void)forwardInvocation:(NSInvocation*)anInvocation;+ (void)doesNotRecognizeSelector:(SEL)aSelector
转载:https://www.jianshu.com/p/9838c7d93087
网友评论