The swizzled in method of a final class resolves static references to its type incorrectly since Xcode 11.4

Since Xcode 11.4 static references to the type within a swizzled in method of a final class will resolve to the class whose method is being replaced. The issue can be reproduced in a playground with the following code:

import Foundation

class A: NSObject {
    @objc dynamic func foo() {
    }
}

final class B: NSObject {
    @objc func swizzled_foo() {
        print("Swizzled foo in \(B.self)")
    }
}

method_exchangeImplementations(
    class_getInstanceMethod(A.self, #selector(A.foo))!,
    class_getInstanceMethod(B.self, #selector(B.swizzled_foo))!
)

A().foo()

In Xcode 11.3 Swizzled foo in B prints as expected but in Xcode 11.4 Swizzled foo in A is printed instead. Removing the final modifier from the B declaration resolves the issue but this doesn't look like an expected behavior.

1 Like

I could see people arguing that swizzled_foo should also be dynamic if it's going to be invoked in "weird" ways, but I think just being @objc ought to be enough to inhibit this optimization. Please file a bug at https://bugs.swift.org!

Filed the bug - [SR-12733] The swizzled in method of a final class resolves static references to its type incorrectly since Xcode 11.4 · Issue #55178 · apple/swift · GitHub

1 Like