Method Swizzling for iOS development is easy to understand

There are plenty of Method Swizzling demos available online if you use Google. I’m not going to post any code here, but I’m going to introduce the concepts, principles, precautions, etc.

Development needs

If the product manager suddenly says, “Add statistics to all pages, that is, every time a user enters the page, they are counted.” Here are a few ideas that come to mind:

  • Manually add

Simply 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, and will be cursed by the developers behind it.

  • inheritance

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

However, this method of modification is still large, and the customization is poor. When new members join, they must be told to inherit from the base class, so this approach is not advisable.

  • Category

We can create a Category for UIViewController, and then introduce that Category in all of our controllers. Of course, we can also add a PCH file and add this Category to the PCH file.

  • Method Swizzling

We can use Apple’s “dark magic” Method Swizzling, which essentially swaps IMP and SEL.

Just a couple of concepts

Selectors, Methods, & Implementations

In Objective-C runtime, selectors, methods, implementations refer to different concepts, but we typically say that in the sending of messages, those three concepts can be swapped. Here is the description in Apple Objective-C Runtime Reference:

  • Selector (typedef struct objc_selector *SEL) : The name used by Selectors to represent a method at run time. Selector is a C-type string that is registered (or mapped) at run time. The Selector is generated by the compiler and automatically mapped to the name and implementation by the runtime when the class is loaded into memory.

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

  • Implementation (typedef id (*IMP)(id, SEL…) ) : This data type refers to the very beginning of a method’s implementation. This method is implemented using standard C method calls for the current CPU architecture. The first argument to this method points to the calling method itself (that is, an in-memory instance object of the class or, in the case of class method calls, a metaclass object). The second argument is the name of the method, selector, followed by the real argument to the method.

The best way to understand the relationship between selector, method, and implementation is that, at runtime, the Class maintains a list of message distributions to handle the proper delivery of messages. The entry to each message list is a Method that maps a key-value pair, where the key value is the Method name selector (SEL) and the value points to implementation (IMP), the function pointer that the Method implements. Method Swizzling modifies the class’s message distribution list so that the existing selector maps to another implementation, and renames the implementation of the native Method to a new selector.

Method Swizzling principle

Method Swizzing happens at run time and is basically used to swap two methods at run time, we can write Method Swizzling code anywhere, but the swap only works after this Method Swilzzling code has run out.

Method Swizzling use caution

Class cluster design pattern

In iOS, NSNumber, NSArray, NSDictionary and other classes are Class Clusters. An implementation of NSArray may consist of multiple classes. Therefore, if you want to Swizzling NSArray, you must obtain its “real body” to Swizzling, direct operation on NSArray is invalid.

The NSArray and NSDictionary classes are listed below, and can be retrieved by the Runtime function.

The name of the class The bard
NSArray __NSArrayI
NSMutableArray __NSArrayM
NSDictionary __NSDictionaryI
NSMutableDictionary __NSDictionaryM

Pay attention to the point

  • Swizzling should always be there+loadPerformed in the
  • Swizzling should always be theredispatch_oncePerformed in the
  • Swizzling in+loadDo not call when executed in[super load]. If I call it multiple times[super load], may appear “Swizzle invalid” illusion, the principle is shown in the following figure:

Swift custom classes use Method Swizzling

There are two requirements to use Method Swizzling in a Swift custom class:

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

Note: For Swift custom classes, because there is no default Objective-C runtime, there is no list of dynamically distributed methods, so if you want to Swizzle Swift type methods, you need to add dynamic flags to both the original method and the replacement method. To indicate that they need to use dynamic distribution mechanisms. And of course classes also inherit from NSObject.

Note again: The following example uses objective-C dynamic distribution. Subclasses of NSObject (UIViewController) can be used directly, and are not Swift custom classes, so it is ok without the dynamic flag.

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

The difference between Objective-C Swift
The Runtime header file #import <objc/runtime.h> Don’t need
Swizzling call in loadmethods initializemethods

Note: The load method is only available in Objective-C and cannot be overloaded in Swift, so it will generate a compilation error no matter how you try it. The next best place to execute Swizzle is initialize, which is the place before calling the first method.

Because Swizzling changes global state, we need to take some precautions at run time. GCD’s dispatch_once ensures atomicity of operations, ensuring that code is executed only once, no matter how many threads.

Method Swizzling practical application

APM(Application Performance Management)

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

  • newrelic.com/ Foreign industry leader
  • www.tingyun.com/ Domestic to cloud
  • www.oneapm.com/ Domestic OneAPM
  • apm.netease.com/ Domestic netease

Foreign information 🤓

Ladders may be needed

  • Nshipster.com/method-swiz…
  • Medium.com/rocknnull/i…
  • medium.com/@abhimurali…
  • Darkdust.net/writings/ob…
  • Blog.newrelic.com/2014/04/16/…
  • Spin.atomicobject.com/2014/12/30/…
  • Wiredcraft.com/blog/method…
  • www.raywenderlich.com/177890/swiz…
  • Petersteinberger.com/blog/2014/a…
  • Iossolves.blogspot.com/2017/11/swi…
  • Iossolves.blogspot.com/2017/11/swi…
  • Sexyswift.wordpress.com/tag/method-…
  • Qiita.com/paming/item…
  • www.swift-studies.com/blog/2014/7…
  • Academy. Realm. IO/posts/sash -…

Small advertisement 🤪

GitHub is an open source iOS debugging tool, one of the functions is to achieve network request capture (code zero intrusion), the principle is also using Method Swizzling, interested children can come to see, also welcome to 🤪 DotzuX.com