【问题标题】:Swift Override Default Init No SubclassSwift Override Default Init 没有子类
【发布时间】:2020-05-02 12:10:15
【问题描述】:

是否可以在不进行子类化的情况下覆盖默认初始化?

我希望在我的应用程序中创建的每个DateFormatter 实例都附加相同的locale。现在,在创建每个实例时,我必须:

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX"

是否有可能在不需要每次都写出语言环境的情况下发生这种情况?我宁愿创建一个 DateFormatter 子类,因为我觉得这有点矫枉过正

谢谢!

【问题讨论】:

    标签: swift overriding init dateformatter


    【解决方案1】:

    没有子类化或修改源代码(显然不能在内置类型的情况下这样做),就无法覆盖类的现有方法。

    但是,对于您的具体情况,您可以简单地添加一个方法/静态变量,该变量返回一个 DateFormatter 特定于您的需求。

    extension DateFormatter {
        static func usPosix() -> DateFormatter {
            let dateFormatter = DateFormatter()
            dateFormatter.locale = Locale(identifier: "en_US_POSIX")
            return dateFormatter
        }
    }
    

    然后你不用调用let dateFormatter = DateFormatter(),而是调用let dateFormatter = DateFormatter.usPosix()

    【讨论】:

    • 我认为您的意思是let dateFormatter = DateFormatter.usPosix(),因为您将其定义为函数而不是变量
    【解决方案2】:

    虽然我个人强烈建议不要混合,但这当然是一种选择。

    首先,首先创建您希望在整个应用程序中使用的您自己的语言环境:

    extension DateFormatter {
        // Note the "@objc" here, this is necessary for altering the runtime logic
        @objc var swizzledLocale: Locale {
            return Locale(identifier: "en_US_POSIX")
        }
    }
    

    接下来,您需要告诉 Swift,每当访问 DateFormatter 的语言环境时,您希望使用新的 swizzledLocale 来代替:

    // get reference to the two getter methods for the properties you want to "switch"
    let orig = #selector(getter: DateFormatter.locale)
    let new = #selector(getter: DateFormatter.swizzledLocale)
    let origMethod = class_getInstanceMethod(DateFormatter.self, orig)!
    let newMethod = class_getInstanceMethod(DateFormatter.self, new)!
    // performs the actual switch so that whenever "locale" is accessed in code, the returned value will be the value of "swizzledLocale"
    method_exchangeImplementations(origMethod, newMethod)
    

    仅此而已!现在,每当您访问任何DateFormatterlocale 时,都会返回一个Locale("en_US_POSIX")

    需要注意的事项:首先,这将改变locale 的所有实例,而不仅仅是您个人在自己的代码中使用的locales。也就是说,如果有任何内部代码依赖于格式化程序的locale,则将始终使用en_US_POSIX。其次,第二个代码块(执行实际调配的代码块)应该只调用一次;考虑将其包装在 dispatch_once 块中,以确保它只运行一次。

    【讨论】:

    • 哇,我不知道我是否真的会实现这个,但这太棒了!谢谢!
    猜你喜欢
    • 2016-06-19
    • 2022-11-13
    • 2016-01-20
    • 2023-04-09
    • 2014-08-22
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多