@TikhonovAlexander: excellente réponse
J'ai modifié le swizzler pour prendre les deux sélecteurs et le rendre plus générique.
Swift 3
private let swizzling: (AnyClass, Selector, Selector) -> () = { forClass, originalSelector, swizzledSelector in
let originalMethod = class_getInstanceMethod(forClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
method_exchangeImplementations(originalMethod, swizzledMethod)
}
// perform swizzling in initialize()
extension UIView {
open override class func initialize() {
// make sure this isn't a subclass
guard self === UIView.self else { return }
let originalSelector = #selector(layoutSubviews)
let swizzledSelector = #selector(swizzled_layoutSubviews)
swizzling(self, originalSelector, swizzledSelector)
}
func swizzled_layoutSubviews() {
swizzled_layoutSubviews()
print("swizzled_layoutSubviews")
}
}
Swift 4
private let swizzling: (AnyClass, Selector, Selector) -> () = { forClass, originalSelector, swizzledSelector in
guard
let originalMethod = class_getInstanceMethod(forClass, originalSelector),
let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)
else { return }
method_exchangeImplementations(originalMethod, swizzledMethod)
}
extension UIView {
static let classInit: Void = {
let originalSelector = #selector(layoutSubviews)
let swizzledSelector = #selector(swizzled_layoutSubviews)
swizzling(UIView.self, originalSelector, swizzledSelector)
}()
@objc func swizzled_layoutSubviews() {
swizzled_layoutSubviews()
print("swizzled_layoutSubviews")
}
}
// perform swizzling in AppDelegate.init()
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
override init() {
super.init()
UIView.classInit
}
}