Writing in the front

As for Method Swizzling, many experts have written detailed articles to introduce it, so I will not teach fish to swim but go deeper. And without further extension, the technology itself is not complex enough to warrant a lengthy discussion. This article is intended to help those unfamiliar with the technology start experimenting with it during actual development.

This is what

  1. The word swizz means “to cheat” in English. Method Swizzling, also known as “Method blending,” “Method blending,” or “Method blending,” is a technique used to interchangeably implement the two methods.
  2. This thing is not used very often, for example, method A implemented this thing, method B implemented this thing, and now you have to implement B with A, B implemented A, even though it is technically possible, what are you trying to achieve? I’ll switch back later, do you remember? What about a third time?
  3. So when might you need this thing? Debugging. If I know how to implement both methods A and B, then I really don’t need to change. But if the implementation of method A is hidden, can I use method B to call method A, add some other functions, and then implement A and B swizz? So when we call method A again, we have A little bit more functionality that we added incidentally. Some people say, well, isn’t that interesting? You can just call method B and get it, so why change it? The point is, how method A is called is probably not up to us. Maybe this method has been called countless times in countless places, so IF I want to batch replace, of course I can swizz.

For chestnuts

For example, in a project, the following method on an instance of NSArray is called N times

func containsObject(anObject: AnyObject) -> BoolCopy the code

Now I want to debug to see where the element is in the data (index) if this method returns true, that is, if the array contains the element we passed in.

func indexOfObject(anObject: AnyObject) -> IntCopy the code

Of course you can just call the above method to get index, but containsObject is used so many times, Xcode doesn’t support Swift refactoring, so I’m not going to change it, so I’ll just use swizz instead.

Here I have posted a complete demo code, you can paste directly into Xcode to run.

import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let arr = NSArray(array: [" Swift ", "Method", "Swizzling"]) print (" -- -- -- -- -- -- -- -- -- -- before Swizzling ") print (arr. ContainsObject (" Swift ")) / / true Print ("-----Swizzling after -----") print(arr.containsobject ("Swift")) Print ("-----Swizzling double -----") print(arr.containsobject ("Swift")) // true}} Extension NSArray {// Replace the default method with func myContainsObject(anObject: If self.myContainsobject (anObject) {print("index: "); AnyObject) -> Bool {// Print the index of the element, which is not available by default. \(self.indexofObject (anObject))")} The following method has been replaced with the default containsObject return self.myContainsObject(anObject)} class func swizz() {let originalMethod = class_getInstanceMethod(NSArray.self, #selector(containsObject(_:))) let swizzledMethod = class_getInstanceMethod(NSArray.self, #selector(myContainsObject(_:))) method_exchangeImplementations(originalMethod, swizzledMethod) } }Copy the code



console

【 Notes 】

  1. I’ve called it three timescontainsObjectThis method, for the second time, its internal implementation ismyContainsObjectThe internal implementation of this method has been replaced.
  2. myContainsObjectThis method looks like an infinite loop at first glance, and it is if you call it directly. But now we’re dynamically determining the internal implementation of this method during RunTime, and when we call this method and go into its function body, its implementation gets swapped out, so inside it, you should putmyContainsObjectChange the word in your headcontainsObject(if it is certain that the two methods do swap implementations at this point).

The last

If what I’ve written can help you with your future debug work, so much the better. If you’re going to use it in a real project… You’d be pretty good if you could use it.