iOS进阶之消息转发(五)

208 阅读1分钟

更多文章请点击下方:

  1. iOS进阶之Runtime初探(一)
  2. iOS进阶之对象与方法的本质(二)
  3. iOS进阶之方法查找(三)
  4. iOS进阶之动态方法解析(四)

源码分析

动态方法解析没有找到,会进入接下来消息转发过程

    // No implementation found, and method resolver didn't help. 
    // Use forwarding.

    imp = (IMP)_objc_msgForward_impcache;
    cache_fill(cls, sel, imp, inst);

这个时候是进入汇编底层

/********************************************************************
*
* id _objc_msgForward(id self, SEL _cmd,...);
*
* _objc_msgForward is the externally-callable
*   function returned by things like method_getImplementation().
* _objc_msgForward_impcache is the function pointer actually stored in
*   method caches.
*
********************************************************************/

	STATIC_ENTRY __objc_msgForward_impcache

	MESSENGER_START
	nop
	MESSENGER_END_SLOW

	// No stret specialization.
	b	__objc_msgForward   进行消息转发

	END_ENTRY __objc_msgForward_impcache

从动态方法解析到消息转发这个过程只是汇编,苹果没有将此部分的代码开源,但是可以通过一个函数来查看整个Objective-C调用过程。

/***********************************************************************
* instrumentObjcMessageSends
**********************************************************************/
// Define this everywhere even if it isn't used to simplify fork() safety code.
spinlock_t objcMsgLogLock;
 
    #if !SUPPORT_MESSAGE_LOGGING

    void	instrumentObjcMessageSends(BOOL flag)
    {
    }

调用的日志信息路径:Private/tmp/msgSend-123456

通过查看消息转发过程,主要有几个函数:

  • forwardingTargetForSelector 在这个函数里我们可以进行自定义处理、crash收集、预防崩溃

  • methodSignatureForSelector

  • forwardInvocation 在这个函数里可以打印系统调用堆栈并上传我们自己后台,如:友盟、bugly;method-swizzling;消息转 发

以上是消息转发的流程,如果未处理的话,系统就提示错误信息并且程序闪退

// Default forward handler halts the process.
__attribute__((noreturn)) void 
objc_defaultForwardHandler(id self, SEL sel)
{
    _objc_fatal("%c[%s %s]: unrecognized selector sent to instance %p "
                "(no message forward handler is installed)", 
                class_isMetaClass(object_getClass(self)) ? '+' : '-', 
                object_getClassName(self), sel_getName(sel), self);
}
void *_objc_forward_handler = (void*)objc_defaultForwardHandler;