<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 Swizzling
of 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 UIViewController
build one Category
for , and import this in all controllers Category
. Of course we can also add a PCH
file and then add this Category
to the PCH
file.
Method Swizzling
We can use Apple's "black magic" Method Swizzling
, Method Swizzling
which is essentially swapping the IMP
sum SEL
.
First understand a few concepts
Selectors, Methods, & Implementations
In Objective-C
the runtime of , selectors
, methods
, implementations
refer 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 Reference
the :
-
Selector(typedef struct objc_selector *SEL)
: Used at runtimeSelectors
to represent the name of a method.Selector
is a C type string that is registered (or mapped) at runtime.Selector
The 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 nameselector
of the method, the method's The real parameters follow.
The best way to understand selector
the relationship method
between implementation
these 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 swizzling
Modified the class's message dispatch list so that the existing one selector
maps to another implementation implementation
, and renamed the native method's implementation to a new one selector
.
Method Swizzling Principle
Method Swizzing
It happens at runtime and is mainly used Method
to swap the two at runtime. We can write Method Swizzling
code anywhere, but the Method Swilzzling
swap will only work after this code is executed.
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
+load
be executed in - Swizzling should always
dispatch_once
be performed in +load
Do 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:
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 <objc/runtime.h> |
unnecessary |
Swizzling call site | load method |
initialize method |
Note: load
The 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 initialize
is , 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_once
can 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
.
- https://newrelic.com/
国外行业老大
- http://www.tingyun.com/
国内听云
- http://www.oneapm.com/
国内OneAPM
- http://apm.netease.com/
国内网易