UIView 方法 swizzling swift 3 [英] UIView method swizzling swift 3
问题描述
我正在尝试根据答案在 swift 3 中实现方法 swizzling 如何在 Swift 3.0 中实现方法 swizzling?
I'm trying to implement method swizzling in swift 3 basing on answer How to implement method 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()
}
}
}
但是在应用程序启动时它会崩溃:
But on app launch it crashes with reason:
'-[UINavigationController swizzled_localization_awakeFromNib]:无法识别的选择器发送到实例 0x7fc7c8820400'
'-[UINavigationController swizzled_localization_awakeFromNib]: unrecognized selector sent to instance 0x7fc7c8820400'
我不明白为什么 swizzled_localization_awakeFromNib 调用 UINavigationController.我在obj-c项目中使用了这个,请问是这个原因吗?它通过 dispatch_once 在 swift 2 中运行良好.
I can't figure out why swizzled_localization_awakeFromNib called on UINavigationController. I am using this in obj-c project, can it be the reason? It worked fine in swift 2 throught dispatch_once.
我尝试在 swizzling(self) 之前放置断点,它按预期在 UIView 上调用了一次.
I tried place breakpoint before swizzling(self), and it called once on UIView, as expected.
推荐答案
问题在于 awakeFromNib
是 NSObject
和不是 UIView
.您的代码将 NSObject
方法与UIView
的方法,调用原方法崩溃当在 UINavigationController
上调用 swizzled 方法时(或 NSObject
的任何其他子类,它不是 UIView
的子类).
The problem is that awakeFromNib
is a method of NSObject
and
not of UIView
. Your code swizzles the NSObject
method with a
method of UIView
, and calling the original method crashes
when the swizzled method is called on UINavigationController
(or any other subclass of NSObject
which is not a subclass of UIView
).
解决方法是尝试添加 swizzled 方法首先是原始名称(如 http://nshipster.com/method-swizzling/ 中所述):
The solution is to try to add the swizzled method with the original name first (as described in 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)
}
}
这篇关于UIView 方法 swizzling swift 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!