UIView方法交换在Swift 3中的实现

3
我将尝试在Swift 3中实现方法交换,基于这个回答: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()
        }
    }

}

当应用程序启动时,它会崩溃,并显示以下原因:

'-[UINavigationController swizzled_localization_awakeFromNib]: unrecognized selector sent to instance 0x7fc7c8820400'

我无法理解为什么在UINavigationController上调用了 swizzled_localization_awakeFromNib。我正在使用obj-c项目,这可能是原因吗?在swift 2中通过dispatch_once运行良好。
我尝试在 swizzling(self) 之前放置断点,并且它在UIView上被调用了一次,正如预期的那样。
1个回答

2
问题在于awakeFromNibNSObject的一个方法,而不是UIView的方法。您的代码将NSObject方法与UIView的方法混合,当在UINavigationController(或任何其他未继承自UIViewNSObject子类)上调用混合方法时会导致调用原始方法崩溃。
解决方案是首先尝试使用原始名称添加混合方法(如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)
    }
}

是的,我已经明白了。在发布我的回答后,我找到了你的答案 :) - art-of-dreams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接