Extend your class:
extension YourClassName { static let classInit: () -> () = { let originalSelector = #selector(originalFunction) let swizzledSelector = #selector(swizzledFunction) swizzle(YourClassName.self, originalSelector, swizzledSelector) } @objc func swizzledFunction() { //Your new implementation } }
Your class (YourClassName) should inherit from NSObject and originalSelector should be a dynamic method.
swizzle is a closure that exchanges the implementations:
private let swizzle: (AnyClass, Selector, Selector) -> () = { fromClass, originalSelector, swizzledSelector in guard let originalMethod = class_getInstanceMethod(fromClass, originalSelector), let swizzledMethod = class_getInstanceMethod(fromClass, swizzledSelector) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) }
You could define swizzle in the class where you are going to do the swizzling. For example the AppDelegate class definition. And then do the swizzling in AppDelegate.init():
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { override init() { super.init() YourClassName.classInit() } }
Example
Here is a concrete example of swizzling, it exchanges the implementation of two methods that take one argument:
class Example: NSObject { @objc dynamic func sayHi(to name: String) { print("Hi", name) } } extension Example { public class func swizzleMethod() { guard let originalMethod = class_getInstanceMethod(Example.self, #selector(Example.sayHi(to:))), let swizzledMethod = class_getInstanceMethod(Example.self, #selector(Example.sayHello(to:))) else { return } method_exchangeImplementations(originalMethod, swizzledMethod) } @objc func sayHello(to name: String) { print("Hello", name) } } Example.swizzleMethod() let a = Example() a.sayHi(to: "Nitish") //Hello Nitish
Swift Native swizzling
As of Swift 5.1, there is a native version of method swizzling that does not rely on Objective-C’s message passing. The @_dynamicReplacement modifier can be used upon a replacement function, and takes as an argument the name of the function that it should replace. The function that is being replaced must be marked with the @dynamic modifier, unless -enable-implicit-dynamic compilation flag is used, which makes the compiler assume that every eligible entity has been marked with the modifier.
For example:
dynamic func original() { print("I am the original") } @_dynamicReplacement(for: original) func replacement() { print("I am the replacement") } original() // prints "I am the replacement"
For more details on dynamic method replacement, visit this Swift forum page.