UIView 方法 swizzling swift 3 [英] UIView method swizzling swift 3

查看:26
本文介绍了UIView 方法 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.

推荐答案

问题在于 awakeFromNibNSObject 和不是 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆