UIView 方法调配 swift 3
UIView method swizzling swift 3
我正在尝试根据答案
在 swift 3 中实现方法混合
这是我的代码:
// 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]:
unrecognized selector sent to instance 0x7fc7c8820400'
我不明白为什么 swizzled_localization_awakeFromNib 调用了 UINavigationController。我在obj-c项目中使用这个,会不会是这个原因?它在 swift 2 到 dispatch_once.
期间运行良好
我尝试在 swizzling(self) 之前放置断点,它按预期在 UIView 上调用了一次。
问题是 awakeFromNib
是 NSObject
的一个方法并且
不属于 UIView
。您的代码将 NSObject
方法与
UIView
的方法,调用原方法崩溃
当在 UINavigationController
上调用 swizzled 方法时
(或 NSObject
的任何其他子类,但不是 UIView
的子类)。
解决方法是尝试添加 swizzled 方法
原名在前(如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)
}
}
我正在尝试根据答案
这是我的代码:
// 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]: unrecognized selector sent to instance 0x7fc7c8820400'
我不明白为什么 swizzled_localization_awakeFromNib 调用了 UINavigationController。我在obj-c项目中使用这个,会不会是这个原因?它在 swift 2 到 dispatch_once.
期间运行良好我尝试在 swizzling(self) 之前放置断点,它按预期在 UIView 上调用了一次。
问题是 awakeFromNib
是 NSObject
的一个方法并且
不属于 UIView
。您的代码将 NSObject
方法与
UIView
的方法,调用原方法崩溃
当在 UINavigationController
上调用 swizzled 方法时
(或 NSObject
的任何其他子类,但不是 UIView
的子类)。
解决方法是尝试添加 swizzled 方法 原名在前(如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)
}
}