Method Swizzling of iOS Development

<p align="center">
<img src ="https://raw.githubusercontent.com/DotzuX/Notes/master/logo.jpeg"/>;
</p>

Method Swizzling of iOS Development

As long as you make good use of Google, there are a lot Method Swizzlingof demos on the Internet. I will not post the code here. I will mainly introduce the concepts, principles, precautions and so on.

development requirements

If the product manager suddenly said: "Add statistical functions to all pages, that is, users will count once when they enter this page." We can think of the following methods:

  • add manully

Simply and rudely add statistics to each controller, copy, paste, copy, paste...
The above method is too low, time-consuming and very difficult to maintain in the future, which will make subsequent developers scolded to death.

  • inherit

We can use inheritance to solve this problem. Create a base class, add statistical methods to this base class, and other classes inherit from this base class.

However, the modification in this way is still very large, and the customization is very poor. After new people join in the future, they must be instructed to inherit from this base class, so this method is not desirable.

  • Category

We can UIViewControllerbuild one Categoryfor , and import this in all controllers Category. Of course we can also add a PCHfile and then add this Categoryto the PCHfile.

  • Method Swizzling

We can use Apple's "black magic" Method Swizzling, Method Swizzlingwhich is essentially swapping the IMPsum SEL.

First understand a few concepts

Selectors, Methods, & Implementations

In Objective-Cthe runtime of , selectors, methods, implementationsrefer to different concepts, but we usually say that these three concepts can be converted into each other during the message sending process. Here's Objective-C Runtime Referencethe :

  • Selector(typedef struct objc_selector *SEL): Used at runtime Selectorsto represent the name of a method. Selectoris a C type string that is registered (or mapped) at runtime. SelectorThe name and implementation mapping is generated by the compiler and automatically performed by the runtime when the class is loaded into memory.

  • Method(typedef struct objc_method *Method):method is an opaque type used to represent the definition of a method.

  • Implementation(typedef id (*IMP)(id, SEL,...)): This data type points to the very beginning of the implementation of a method. This method is implemented using standard C method calls for current CPU architectures. The first parameter of the method points to the calling method itself (that is, the instance object of the class in memory, if the class method is called, the pointer points to the metaclass object ( metaclass). The second parameter is the name selectorof the method, the method's The real parameters follow.

The best way to understand selectorthe relationship methodbetween implementationthese three concepts is: At runtime, the class ( Class) maintains a message distribution list to resolve the correct sending of messages. The entry of each message list is a method ( Method), which maps a pair of key-value pairs, where the key is the name of the method and the selector(SEL)value is the function pointer to the implementation of the method implementation(IMP). Method swizzlingModified the class's message dispatch list so that the existing one selectormaps to another implementation implementation, and renamed the native method's implementation to a new one selector.

Method Swizzling Principle

Method SwizzingIt happens at runtime and is mainly used Methodto swap the two at runtime. We can write Method Swizzlingcode anywhere, but the Method Swilzzlingswap will only work after this code is executed.

Method Swizzling of iOS Development

Method Swizzling of iOS Development

Method Swizzling Notes

class cluster design pattern

In iOS, NSNumber, NSArray, NSDictionary and other classes are class clusters ( Class Clusters), and an NSArray implementation may consist of multiple classes.
Therefore, if you want to perform Swizzling on NSArray, you must obtain its "real body" for Swizzling, and it is invalid to operate on NSArray directly.

The class names of the NSArray and NSDictionary classes are listed below, which can be retrieved through the Runtime function.

class name real body
NSArray __NSArrayI
NSMutableArray __NSArrayM
NSDictionary __NSDictionaryI
NSMutableDictionary __NSDictionaryM

Points to Note

  • Swizzling should always +loadbe executed in
  • Swizzling should always dispatch_oncebe performed in
  • +loadDo not call when Swizzling is executing in [super load]. If it is called multiple times [super load], the illusion of "Swizzle is invalid" may appear. The principle is shown in the following figure:

Method Swizzling of iOS Development

Using Method Swizzling in Swift Custom Classes

To use Method Swizzling in a Swift custom class there are two prerequisites:

  • Classes containing Swizzle methods need to inherit from NSObject
  • Methods that require Swizzle must have dynamic attributes

Note: For Swift custom classes, because the Objective-C runtime is not used by default, there is no dynamically dispatched method list, so if you want to Swizzle a Swift type method, you need to use both the original method and the replacement method. Add the dynamic flag to indicate that they need to use the dynamic dispatch mechanism. Of course, the class should also inherit from NSObject.

Another note: The following example uses the dynamic dispatch of Objective-C, which can be used directly for the subclass of NSObject (UIViewController), not a custom class in Swift, so it is also possible to not add the dynamic tag.

Similarities and differences between Objective-C and Swift in Method Swizzling

the difference Objective-C Swift
Runtime header files #import &lt;objc/runtime.h&gt; unnecessary
Swizzling call site loadmethod initializemethod

Note: loadThe method is only available in Objective-C, and cannot be overloaded in Swift, no matter how you try, a compilation error will be reported. The best place to execute Swizzle next initializeis , this is the place before the first method is called.

Because Swizzling mutates global state, we need to take some precautions at runtime. GCD's dispatch_oncecan guarantee the atomicity of operations, ensuring that the code is executed only once, no matter how many threads there are.

Method Swizzling in action

APM (Application Performance Management)

The principle of network monitoring should be hook NSURLConnection, NSURLSession. The principle of crash collection should be hook NSException.

foreign information

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324735019&siteId=291194637