Principle of OC message sending and forwarding mechanism

Objective-C (OC) is an object-oriented programming language with unique mechanisms in message passing and method invocation. In OC, objects call methods through messages instead of calling functions directly like traditional programming languages. This article will deeply explore the principles of OC’s message sending and forwarding mechanism, including its basic concepts, implementation process, code examples, and practical application scenarios.

Step 1: What is the message sending and forwarding mechanism?

In Objective-C, communication between objects is achieved through message passing. When an object wants to call a method on another object, it sends a message, and the object that receives the message responds to the message. This method is different from traditional function calls, making OC more dynamic and flexible.

The message sending and forwarding mechanism is divided into three stages:

  1. Message Sending: When an object receives a message, it will first look in its own method list to see if there is a method corresponding to the message. If found, the method will be executed; if not found, the next phase will be entered.

  2. Message Forwarding: If the object cannot find the method corresponding to the message, it will enter the message forwarding process. At this stage, objects have the opportunity to forward messages to other objects.

  3. Handling Unknown Messages: If no suitable method is found after message forwarding, the system will call the -doesNotRecognizeSelector: method, which will throw an exception by default, but It can also be overridden by developers to perform other operations.

Step 2: Principle of message sending

Message sending is one of the core mechanisms of OC, which makes method invocation more dynamic and flexible. The principle of message sending can be summarized as the following steps:

  1. Creating a message: When an object wants to call a method, it creates a message, including the recipient of the message, the method name (selector), and the method’s parameters.

  2. Find methods: The object looks in its own method list (method distribution table) to see if there is a method corresponding to the message. A method distribution table is a map that associates selectors with method implementations.

  3. Call method: If the method corresponding to the message is found, the object will directly call the method and execute it. If not found, the message will enter the message forwarding stage.

Step 3: Principle of message forwarding

When an object cannot find a method corresponding to a message, it enters the message forwarding process. The principle of message forwarding can be summarized as the following steps:

  1. Start of message forwarding: After the object receives a message that cannot be processed, it will call the -forwardingTargetForSelector: method, which allows the object to forward the message to other objects. If a valid object is returned, the message will be forwarded to that object.

  2. Alternate Receiver: If the -forwardingTargetForSelector: method returns nil, the object will continue to look for an alternate receiver (Alternate Receiver), which is usually another object. Alternate recipients can be specified by overriding the + (id)forwardingTargetForSelector:(SEL)aSelector class method.

  3. Dynamic method resolution: If there is no alternative receiver or the alternative receiver cannot handle the message, the object will call the + resolveInstanceMethod: or + resolveClassMethod: method to dynamically add methods. This allows developers to add new methods to objects at runtime.

  4. Complete message forwarding: If the previous steps fail, the object will call the -forwardInvocation: method and pass the message to the NSInvocation object. this method. In the -forwardInvocation: method, developers can manually handle the forwarding of messages, including sending messages to other objects or performing other operations.

Step 4: Code example for message sending and forwarding

Let us demonstrate the process of message sending and forwarding through a simple code example:

#import <Foundation/Foundation.h>

@interface MyObject : NSObject

- (void)methodA;

@end

@implementationMyObject

- (void)methodA {
    NSLog(@"Method A is called");
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MyObject *obj = [[MyObject alloc] init];
        
        // Call existing method
        [obj methodA]; // Output "Method A is called"
        
        //Call a non-existent method
        [obj methodB]; // Trigger message forwarding
        
        //Use dynamic method to parse and add method
        class_addMethod([MyObject class], @selector(methodB), class_getMethodImplementation([MyObject class], @selector(methodA)), "v@:");
        
        // Call the method again
        [obj methodB]; // Output "Method A is called"
    }
    return 0;
}

In this example, we first create a MyObject class, which contains the methodA method. Then, we create an object obj and try to call the methodA method, which is an existing method.

Next, we try to call a non-existent method methodB, which will trigger the message forwarding process. During the message forwarding process, we use dynamic method parsing to associate the implementation of the methodB method with the implementation of the methodA method. Finally, the methodB method is called again, which will execute the implementation of methodA.

Step 5: Practical application scenarios of message sending and forwarding

Message sending and forwarding mechanisms have a wide range of uses in practical applications. The following are some common application scenarios:

  1. Dynamic method resolution: Allows new methods to be added to objects at runtime, which is very useful for plug-in systems and modular development. For example, plug-in functionality can be dynamically added or removed as needed.

  2. Message forwarding: Messages can be forwarded to other objects, thereby implementing the agency mode, delegation mode and chain of responsibility mode. This allows objects to delegate tasks to other objects without knowing the specific implementation.

  3. Extending functionality without modifying the source code: In some cases, the source code of a class cannot be modified, but its functionality still needs to be extended. Message forwarding allows us to extend the functionality of an object through subclassing or other means.

  4. AOP (aspect-oriented programming): You can use message sending and forwarding to implement AOP, for example, adding logging, performance monitoring, and exception handling before and after method calls.

  5. Unknown message handling: If an object needs to handle unknown messages or commands, the message forwarding mechanism can be used to handle these situations. For example, a general message handler can perform different operations based on different message types.

Step 6: Things to note

When using the message sending and forwarding mechanism, you need to pay attention to the following points:

  1. Performance impact: The message sending and forwarding mechanism may bring certain performance overhead because it involves dynamic search methods and message delivery. It should be used with caution in scenarios where high performance is required.

  2. Naming Conventions: To avoid confusion and errors, good method naming conventions should be followed to ensure that method names are consistent with message names.

  3. Complexity of dynamic method parsing and message forwarding: Dynamic method parsing and message forwarding are powerful mechanisms, but they are also complex. Careful consideration and testing is required when used to ensure that unknown messages are handled correctly.

  4. Don’t abuse: Messaging and forwarding mechanisms are powerful tools, but they should not be abused. It should generally be used as a fallback mechanism for handling messages in specific situations, rather than in a regular programming manner.

Step 7: Summary

OC’s message sending and forwarding mechanism is a core feature of this programming language, which makes method calls more dynamic and flexible. Understanding the principles of message sending and forwarding can help developers make better use of this mechanism and implement object-oriented programming design patterns and ideas.

The message sending and forwarding mechanism has a wide range of practical application scenarios, including dynamic method parsing, message forwarding, AOP programming, extended functions that cannot modify the source code, etc. Through in-depth research and practice, developers can better master the message sending and forwarding mechanism, improve the flexibility and scalability of the code, and ensure the maintainability and stability of the application. This mechanism makes OC a powerful object-oriented programming language, worthy of in-depth study and exploration by developers.