So when I tried to swizzle UIImage's init(named:) so that I could set the accessibility identifier with the image's name, it seems like, even though I am calling method_exchangeImplementation, both my swizzled method ftg_imageNamed(named name: String) and init(named:) call my swizzled method: ftg_imageNamed(named name: String) creating an infinite loop. Why is that?
Calling method_exchangeImplementation
extension UIImage {
static func swizzleInitImplementation() {
let originalSelector = #selector(UIImage.init(named:))
let swizzledSelector = #selector(UIImage.ftg_imageNamed(named:))
let imgSelf: AnyClass = self.classForCoder()
guard let originalMethod = class_getClassMethod(imgSelf, originalSelector),
let swizzledMethod = class_getClassMethod(imgSelf, swizzledSelector) else {
assertionFailure("The methodsw are not found")
return
}
method_exchangeImplementations(originalMethod, swizzledMethod)
}
@objc static func ftg_imageNamed(named name: String) {
setAccessibilityLabel(name)
self.ftg_imageNamed(named: name)
}
}
The manual implementation which failed the same way.
extension UIImage {
static func swizzleInitImplementation() {
let originalSelector = #selector(UIImage.init(named:))
let swizzledSelector = #selector(UIImage.ftg_imageNamed(named:))
let imgSelf: AnyClass = self.classForCoder()
guard let originalMethod = class_getClassMethod(imgSelf, originalSelector),
let swizzledMethod = class_getClassMethod(imgSelf, swizzledSelector) else {
assertionFailure("The methodsw are not found")
return
}
let imp1 = method_getImplementation(originalMethod)
let imp2 = method_getImplementation(swizzledMethod)
method_setImplementation(originalMethod, imp2)
method_setImplementation(swizzledMethod, imp1)
}
@objc static func ftg_imageNamed(named name: String) {
setAccessibilityLabel(name)
self.ftg_imageNamed(named: name)
}
}
Your swizzling seems "ok" until
self.UI(named: name). So check that method for infinite loop problem.Now, this is a bad implementation of swizzling.
UIImage.init(named:)returns an instance ofUIImage, where swizzled methodUIImage.ftg_imageNamed(named:)returnsVoid. Both original and swizzled method should have the same params and return type, the implementation may vary.You should consider a simple extension method to achieve what you want instead of swizzling.
Edit
use it as