Preface:

In the previous article about messaging, there was a question: what happens to an object when it receives an undecipherable message? For a class to understand a message, we must implement the corresponding method in code. However, sending a message to a class at compile time that it cannot read is not an error, because methods can continue to be added to the class at run time, so the compiler has no way of knowing at compile time whether or not there will be a method implementation in the class. When an object receives an undecipherable message, a “message forwarding” mechanism is initiated by which the programmer tells the object what to do with the location message.

Dynamic method parsing

When an object receives an undecipherable message, it first calls the following class methods of its class: + (BOOL)resolveInstanceMethod:(SEL)selector this method takes the unknown selector and returns a Boolean value indicating whether the class can create a new real class to handle the selector. Before moving on to the forward mechanism, the class has the opportunity to add a method that handles this selector. Add an unimplemented method that is not an instance method but a class method, and the runtime calls another method, similar to “resolveInstanceMethod”, called “resolveClassMethod:”. The premise of using this approach is that the implementation code of the related method is already written, just waiting to be dynamically inserted into the class at runtime. This method is often used to implement @dynamic properties, for example, when accessing nS-Managed Dobjects objects in the CoreData framework, because the storage method required to implement these properties is determined by the compiler.

Standby receiver

The current receiver has a second chance to process the unknown selectors, at which point the run-time system asks it if it can forward the message to another receiver for processing. Steps and the corresponding treatment methods are as follows: – (id) forwardingTargetForSelector: (SEL) aSelector method on behalf of the unknown parameter selection, if the current receiver redundant objects can be found, it is returned, it is returned, if can’t find, it returns nil. Through this scheme, we can use composition to simulate some of the characteristics of multiple inheritance. Inside an object, there may be a series of other objects that can be returned by this method with related internal objects that can handle a selector, so that it appears to the outside world as if the object itself handled the messages. Please note that we cannot manipulate messages forwarded through this step. If you want to modify the message content before sending it to the standby receiver, you need to do so through the full message forwarding mechanism.

Complete message forwarding

If the forwarding algorithm has reached this point, the only thing that can be done is to enable the full message forwarding mechanism. The NSInvocation object is first created to enclose all the details related to the as-yet-unprocessed message. This object contains selectors, targets, and parameters. When the NSInvocation object is triggered, the Message dispatch system itself assigns the message to the target. This step calls the following method to forward the message: – (void)forwardInvocation:(NSInvocation *)anInvocation this method is simple: Simply change the invocation target so that the message is invoked on the new target. However, this implementation is equivalent to that of the “standby receiver” scheme, so few people use such a simple implementation. A useful way to do this is to change the message content in some way, such as append a parameter, change a selector, etc., before firing the message. When implementing this method, you need to call a method of the same name of the superclass if you find that a calling operation should not be handled by this class. That way, every class in the inheritance hierarchy has a chance to handle the call request, up to NSObject. If the last call the NSObject class methods, the method will then call “doesNotRecognizeSelector:” to throw an exception, the exception that selector eventually failed to be processed.

The entire message forwarding process

At each step, the receiver has an opportunity to process the message. The further you go, the more expensive it becomes to process the message. It is best to do this in the first step so that the runtime system can cache the method. If an instance of this class also receives a selector of the same name later, there is no need to start the message forwarding process at all. If you want to forward the message to the standby receiver in step 3, you might as well forward the forward operation to step 2. Because the third step only modifs the invocation target, this change is easier to implement in the second step, otherwise you would have to create and handle the full NSInvocation.

The main points of

1️ If the object cannot respond to a selector, the message forwarding process is entered.

2️ dissolving function through the dynamic method of running period, we can add a certain method into the class when it is needed.

3️ one can transfer some selectors that it cannot decipher to other objects for processing.

4️ after the above two steps, if the selectors still cannot be processed, the complete message forwarding mechanism will be started.