preface

Study hard, not anxious not impatient. Make little progress every day

The previous article covered message dynamic resolution, which provides a remedy when a functional method is not implemented. After the dynamic resolution system performed forwardingTargetForSelector respectively, methodSignatureForSelector process these two functions, that is the message forwarding process, then we explain, what is the message forwarding process.

forward

Fast forward

Find imp process into forwardingTargetForSelector internal, but because the class does not implement aSelector, the program still complains:

Public class in the last article tells the story of a little train of thought, then we in forwardingTargetForSelector function, try to SEL redirection, SEL of implementing other classes;

The QLYTeacher class implements the sayHi function, redirects the sayHi function of QLYPerson to the QLYTeacher class, and the program runs without any problems, and the code is clear and not bloated. The idea of public function extraction and encapsulation is well implemented: If other classes do not implement a method, you can implement it in the public class or dynamically add aSelector directly in the public class.

But if in QLYTeacher, also does not implement sayHi functions, procedures continue to report errors, a message will be executed to methodSignatureForSelector function forward, slow process,

Slowly forward

In the QLYPerson class implementation of slow search, the system or crash, and cut the QLYPerson class slow search process is not executed;

The reason: QLYPerson class to achieve fast search, by redirecting to QLYTeacher, so will execute QLYTeacher class to find SEL IMP process, and then execute QLYTeacher dynamic resolution, QLYTeacher class fast search process, But because QLYTeacher does not realize the fast search process, it directly crashes inside QLYTeacher;

So, for the sake of looking at the slow process, the QLYPerson class’s quick lookup process is temporarily blocked;

The slow Invocation was executed, but it still broke because the slow Invocation needs to be used together with another function, forwardInvocation, and the NSMethodSignature parameter is returned.

v@:: Default parameter encoding; Type cannot be passed null; it must be passed a recognizable signature.

At this point, the slow lookup process ends; But there is no business processing; Also, the forwardInvocation is just the statement, what is it useful for?

  • forwardInvocationStore slow lookup process transactions until the next call.

Next check to see if the anInvocation stores the current process;

Slow search process, in order to compatible with errors in the program, if the call an unrealized method, but does not require any business processing, slow search process, in order to improve the program, so as to help us to avoid the error of a system crash, to make our system more perfect, perfect;

So, if we implement such a slow lookup in our NSObject base class, we can avoid a system-wide crash; But the use of slow search process, also indicated that the execution of a set of IMP search process, performance has a lot of consumption;

Forward process

Through the above content, I have a certain understanding of the fast and slow search process of message forwarding, but at the bottom, what is the message forwarding process? That’s something we need to continue to explore;

From the doesNotRecognizeSelector function of the CoreFoundation framework, we know that the crash is caused by the method not found. Using the BT instruction, we print out the whole stack information. We can see that the crash information comes from the doesNotRecognizeSelector function of the CoreFoundation framework. The ___forwarding___ and _CF_forwarding_prep_0 functions are executed before the main function, so let’s focus on the business logic of these functions.

Since the CoreFoundation framework is not open source, understanding the mechanics of message forwarding requires a new tool:

  • 1. Download the Hopper Disassembler tool.
  • 2, getCoreFoundationThe executable of the framework;
  • 3. Open it with Hopper DisassemblerCoreFoundationThe executable of the framework;

Next, start disassembly;

If the forwarding function does not exist, run the _objc_msgSend function to obtain the class. If the forwarding function does exist, run the _objc_msgSend_stret function to obtain the class. Then determine whether to taggedpointer small object types, and then make a series of displacement of the operation, then we can see the logic of news fast forwarding forwardingTargetForSelector:

If the class cannot respond to the fast forwarding process, slow forwarding is performed:

The low-level slow invocation is not what you thought it would be, and it’s the forwardStackInvocation: function that’s not in OC, it’s the low-level invocation, so it’s not supposed to respond. Follow the low-level redirect logic. Next we execute the loc_64C19 block logic:

conclusion