“This is the first day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021”

Methods exchange

At run time, the class maintains a list of methods that address the proper handling of messages. The method list maps the method name to the Implementation of the associated method, where the key value is the method name Selector(SEL) and the value points to the Implementation’s function pointer Implementation(IMP).

In the OC Runtime feature, the method of calling an object is to send a message to the object. Find the corresponding SEL from the method list by looking up the list of methods that receive the message object. This SEL corresponds to an IMP. Find the corresponding method call through this IMP. Method swapping modifies the mapping between SEL and IMP in the class’s method list so that an existing SEL maps to another IMP


Method interchange

  • About +(void)initialize and +(void) Load

    • +(void)initializeThis method is called the first time a class is called, and only once during the entire program run
    • + (void)loadThis method is called when the program is started. In other words, the load method is called as soon as the program is started, and only once during the entire program run
  • Add a Category to the class of the method you want to swap, and then add the method swap to the + (void)load method of the Category

  • Obtain method address

    Method class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name)
    Copy the code
  • Exchange method address, equivalent to exchange implementation

    void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) 
    Copy the code

Method interchange example

Usage scenario: If you need to extend a feature without changing the original code, you can use method swapping

Start by adding a Category to the class of the method you want to swap

@interface NSURL (ExchangeMethod)

@end


#import "NSURL+ExchangeMethod.h"
#import <objc/runtime.h>
@implementation NSURL (ExchangeMethod)

// Called when the class is loaded
+ (void)load{
    NSLog(@"load");
    
    // Get the method address
    Method  urlWithStr = class_getClassMethod([NSURL class], @selector(URLWithString:));
    Method  XYURLWithStr = class_getClassMethod([NSURL class], @selector(XYURLWithStr:));
    
    // Switch method address, equivalent to switch implementation
    method_exchangeImplementations(urlWithStr,XYURLWithStr);
}


// The system method URLWithString cannot be overridden in the class because it overwrites the system functionality and cannot call super in the class.
+ (instancetype)XYURLWithStr:(NSString*)str{
    /** ('XYURLWithStr'); /** ('XYURLWithStr'); Note: there is no recursive operation. */
    NSURL *url = [NSURL XYURLWithStr:str];// Call the system method implementation
    if (url == nil){
        NSLog(@"Perform custom links");
    }
    return url;
}
@end
Copy the code

A function call

#import "ViewController.h"
#import "NSURL+ExchangeMethod.h"
@interface ViewController ()

@end



@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURL *url = [NSURL URLWithString:@"Http://www.baidu.com/ error"];
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
}
@end
Copy the code