Objective-C Runtime: Method Swizzling, objectivecruntime

Source: Internet
Author: User

Objective-C Runtime: Method Swizzling, objectivecruntime

Understanding Method Swizzling is a great opportunity to learn the runtime mechanism. I will not do much work here. I will only translate the article "Method Swizzling" published by Mattt Thompson in nshipster.

Method Swizzling is a technique used to change the actual implementation of a selector. Through this technology, we can modify the implementation of methods by modifying the selector function in the class distribution table at runtime.

For example, we want to track the number of times each view controller displays to the user in the program: Of course, we can add the tracking code to the viewDidAppear of each view controller; but this is too troublesome, duplicate code needs to be written in each view controller. Creating a subclass may be an implementation method, but you must also create a subclass of UIViewController, UITableViewController, UINavigationController, and view controller in other UIKit. This also produces a lot of repeated code.

In this case, we can use Method Swizzling, as shown in the Code:

#import <objc/runtime.h>@implementation UIViewController (Tracking)+ (void)load {        static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        Class class = [self class];                 // When swizzling a class method, use the following:                    // Class class = object_getClass((id)self);        SEL originalSelector = @selector(viewWillAppear:);                    SEL swizzledSelector = @selector(xxx_viewWillAppear:);        Method originalMethod = class_getInstanceMethod(class, originalSelector);                    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);        BOOL didAddMethod =                        class_addMethod(class,                originalSelector,                method_getImplementation(swizzledMethod),                method_getTypeEncoding(swizzledMethod));        if (didAddMethod) {                        class_replaceMethod(class,                swizzledSelector,                method_getImplementation(originalMethod),                method_getTypeEncoding(originalMethod));        } else {            method_exchangeImplementations(originalMethod, swizzledMethod);        }    });}#pragma mark - Method Swizzling- (void)xxx_viewWillAppear:(BOOL)animated {        [self xxx_viewWillAppear:animated];    NSLog(@"viewWillAppear: %@", self);}@end

Here, we use method swizzling to modify the function pointer of @ selector (viewWillAppear :) of UIViewController, so that it points to the custom xxx_viewWillAppear implementation. In this way, a log is printed when the object of UIViewController and its subclass calls viewWillAppear.

The above example shows how to use method swizzling to inject some of our new operations into a class. Of course, method swizzling can be used in many other scenarios. Here we will talk about some notes for using method swizzling:

Swizzling should always be executed in + load

In Objective-C, two methods of each class are automatically called at runtime. + Load is called when the class is initially loaded, and + initialize is called before the class method or instance method of the class is called for the first time. These two methods are optional and will be called only when they are implemented. Because method swizzling will affect the global status of the class, we should try to avoid competition in concurrent processing. + Load can ensure that the class is loaded during initialization and the behavior changes at the application level is consistent. In contrast, + initialize does not provide this guarantee during its execution-in fact, if the application does not send messages to this class, it may never be called.

Swizzling should always be executed in dispatch_once

It is the same as above, because swizzling will change the global state, so we need to take some preventive measures at runtime. Atomicity is such a measure, which ensures that the code is executed only once, no matter how many threads there are. The dispatch_once of GCD ensures this behavior. We should use it as the best practice of method swizzling.

Selector, method, and implementation

In Objective-C, selector, method, and implementation are special points in the runtime, although in general, these terms are mostly used in the process description of message sending.

Here are some descriptions of these terms in Objective-C Runtime Reference:

The best way to understand the relationship between these terms is: A class maintains a message shard that can be received during running; Each entry in the Shard is a Method ), the key is a specific name, that is, the selector (SEL), which corresponds to an Implementation (IMP), that is, a pointer to the underlying C function.

To swizzle a method, we can map the existing selector of a method to different implementations in the sub-table, and associate the original implementation of the selector to a new selector.

Call _ cmd

Let's look back at the implementation code of the previous new method:

- (void)xxx_viewWillAppear:(BOOL)animated {    [self xxx_viewWillAppear:animated];    NSLog(@"viewWillAppear: %@", NSStringFromClass([self class]));}

It seems like an infinite loop. But surprisingly, this is not the case. In the swizzling process, [self xxx_viewWillAppear: animated] In the method has been re-specified to-viewWillAppear: In the UIViewController class. In this case, there is no infinite loop. However, if we call [self viewWillAppear: animated], an infinite loop is generated, because the implementation of this method has been re-specified as xxx_viewWillAppear: at runtime.

Notes

Swizzling is often called a black magic, which can easily lead to unpredictable behaviors and unpredictable consequences. Although it is not the safest, it is safer to take the following preventive measures:

  

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.