【问题标题】:UIView method swizzling swift 3UIView 方法 swizzling swift 3
【发布时间】:2017-02-19 08:21:03
【问题描述】:

我正在尝试根据答案 How to implement method swizzling swift 3.0? 在 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]: 无法识别的选择器发送到实例 0x7fc7c8820400'

我不明白为什么 swizzled_localization_awakeFromNib 调用 UINavigationController。我在 obj-c 项目中使用它,这可能是原因吗?它在 swift 2 throught dispatch_once 中运行良好。

我尝试在 swizzling(self) 之前放置断点,它在 UIView 上调用了一次,正如预期的那样。

【问题讨论】:

    标签: ios swift uiview swift3 swizzling


    【解决方案1】:

    问题是awakeFromNibNSObject 和 不是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)
        }
    }
    

    【讨论】:

    • 是的,已经知道了。在发布我自己的答案后找到你的答案:)
    猜你喜欢
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 2017-02-09
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 2014-07-28
    相关资源
    最近更新 更多