UIView方法swizzling swift 3

我正在尝试在swift中快速实现方法3基于答案如何实现方法swizzling swift 3.0?

这是我的代码:

// MARK: - Swizzling private let swizzling: (UIView.Type) -> () = { view in let originalSelector = #selector(view.awakeFromNib) let swizzledSelector = #selector(view.swizzled_localization_awakeFromNib) let originalMethod = class_getInstanceMethod(view, originalSelector) let swizzledMethod = class_getInstanceMethod(view, swizzledSelector) method_exchangeImplementations(originalMethod, swizzledMethod) } extension UIView { open override class func initialize() { guard self === UIView.self else { return } swizzling(self) } func swizzled_localization_awakeFromNib() { swizzled_localization_awakeFromNib() if let localizableView = self as? Localizable { localizableView.localize() } } } 

但在应用程序启动时,它崩溃的原因是:

' – [UINavigationController swizzled_localization_awakeFromNib]:无法识别的select器发送到实例0x7fc7c8820400'

我无法弄清楚为什么swizzled_localization_awakeFromNib在UINavigationController上调用。 我在obj-c项目中使用这个,可以这样做吗? 它在swift 2到dispatch_once中工作正常。

我在尝试使用位置断点之前(swizzling(self)) ,并按照预期在UIView上调用一次。

问题是awakeFromNibNSObject的方法,而不是UIView 。 你的代码使用UIView的方法调用NSObject方法,当在UINavigationController (或者NSObject任何其他子类,不是UIView的子类)上调用swizzled方法时调用原始方法崩溃。

解决scheme是尝试添加与原来的名字优先(如http://nshipster.com/method-swizzling/中所述 ):

 private let swizzling: (UIView.Type) -> () = { view in let originalSelector = #selector(view.awakeFromNib) let swizzledSelector = #selector(view.swizzled_localization_awakeFromNib) let originalMethod = class_getInstanceMethod(view, originalSelector) let swizzledMethod = class_getInstanceMethod(view, swizzledSelector) let didAddMethod = class_addMethod(view, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) if didAddMethod { class_replaceMethod(view, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) } else { method_exchangeImplementations(originalMethod, swizzledMethod) } }