ios - UIView 方法 swizzling swift 3

标签 ios swift uiview swift3 swizzling

我正在尝试根据答案 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]: unrecognized selector sent to instance 0x7fc7c8820400'

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

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

最佳答案

问题是 awakeFromNibNSObject 的一个方法并且 不是 UIView。您的代码使用 NSObject 方法调配 UIView的方法,调用原方法崩溃 当在 UINavigationController 上调用 swizzled 方法时 (或不是 UIView 子类的 NSObject 的任何其他子类)。

解决方案是尝试添加 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)
    }
}

关于ios - UIView 方法 swizzling swift 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42325078/

相关文章:

iOS-向应用程序窗口添加导航栏

ios - 在 Xcode 中从 App store 复制 iOS 应用程序更新过程

ios - 未调用 UIPageViewController 委托(delegate)方法

iphone - 更改 URL 并重新加载 UIWebView?

iOS 如何手动调整 UIImageView 使其像按钮一样工作?

iphone - 'self.window addSubview : view ' 中的 self 有什么用?

ios - 如何在 iOS 中设置 Apple Watch 图标图像

Swift - 从函数返回的类型实例化类

swift - 类型 '[String]' 不符合协议(protocol) 'Equatable'

ios - 使用 MVVM 时,如何在子 ViewController 中扩展 ViewModel?