0

I'm playing around with swizzling. I've written this code to exchange implementation for a method of a class with extension.

@objc class A: NSObject {
    @objc func name() {
        print("this is class A")
    }
}

extension A {
    @objc func myName() {
        self.myName()
        print("this is my extension version of A")
    }
}

@objc class B: A {
    @objc override func name() {
        super.name()
    }

    @objc override func myName() {
        super.myName()
    }
}

// swizzling name and myName
let originalSelector = #selector(A.name)
let swizzledSelector = #selector(A.myName)

guard let swizzledMethod = class_getInstanceMethod(A.self, swizzledSelector) else {
    fatalError()
}

if let originalMethod = class_getInstanceMethod(A.self, originalSelector)  {
    method_exchangeImplementations(originalMethod, swizzledMethod)
    print("replaced")
}

now i run this code to test it:

let b = B()
print("-----")
b.name()
print("-----")
b.myName()

I expect this output:

replaced
-----
this is class A
this is my extension version of A
-----
this is class A

but what I actually see in log is this:

replaced
-----
this is class A
-----
this is class A

what I'm doing or expecting wrong?

1 Answers1

1

Refer to swift method_exchangeImplementations not work

By adding the dynamic declaration modifier, the swizzling happens properly. Without this, the call to method_exchangeImplementations() does not have the intended effect. See https://swiftunboxed.com/interop/objc-dynamic/ for more information about dynamic dispatch.

So like this:

@objc dynamic func name() {
    print("this is class A")
}
BenW
  • 321
  • 2
  • 4
  • "the call ... has no effect" – you might wish to qualify this. The call has an effect – the dynamically looked up method implementations are swapped – and that will be seen from Objective-C. However Swift will (may?) avoid dynamic dispatch and compile a direct call to the original method implementation *unless* the `dynamic` keyword is present. – CRD Feb 24 '20 at 18:13
  • @BenW tnx, you are true and it's worked as I expected. so function like viewDidAppear in UIViewController all have this dynamic definition? – Jafar Khoshtabiat Feb 25 '20 at 05:19