简体   繁体   English

Swift 覆盖默认初始化没有子类

[英]Swift Override Default Init No Subclass

Is it possible to override a default init without subclassing?是否可以在没有子类化的情况下覆盖默认初始化?

I want every instance of DateFormatter created in my app to have the same locale attached to it.我希望在我的应用程序中创建的每个DateFormatter实例都附加相同的locale Right now, upon each instance creation, I have to:现在,在创建每个实例时,我必须:

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

Is it possible to have this happen without the need to write out the locale every single time?是否有可能在不需要每次都写出语言环境的情况下发生这种情况? I'd prefer to not create a DateFormatter subclass as I feel that's a bit of overkill我宁愿创建DateFormatter子类,因为我觉得这是一个有点矫枉过正

Thanks!谢谢!

There is no way to override an existing method of a class without subclassing it or modifying the source code (which you obviously can't do in case of built-in types).如果不继承类或修改源代码,就无法覆盖类的现有方法(对于内置类型,您显然不能这样做)。

However, for your specific case, you could simply add a method/static variable that returns a DateFormatter specific to your needs.但是,对于您的特定情况,您可以简单地添加一个方法/静态变量,该变量返回特定于您的需要的DateFormatter

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

And then instead of calling let dateFormatter = DateFormatter() , you do let dateFormatter = DateFormatter.usPosix()然后不是调用let dateFormatter = DateFormatter() ,而是let dateFormatter = DateFormatter.usPosix()

While I personally HIGHLY advise against swizzling, that is certainly an option here.虽然我个人强烈建议不要使用 swizzling,但这当然是一个选择。

First, start by creating your own locale that you want to be used throughout your app:首先,首先创建您想要在整个应用程序中使用的自己的语言环境:

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

Next, you'll want to tell Swift that whenever a DateFormatter 's locale is accessed, you want your new swizzledLocale to be used instead:接下来,您需要告诉 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)

And that's all there is to it!这就是全部! Now whenever you access any DateFormatter 's locale , a Locale("en_US_POSIX") will be returned.现在,每当您访问任何DateFormatterlocale ,都会返回Locale("en_US_POSIX")

Some things to note: first, this will alter ALL instances of locale , not just the locale s that you personally use in your own code.需要注意的一些事情:首先,这将改变locale所有实例,而不仅仅是您个人在自己的代码中使用的locale That is, if there's any internal code that relies on a formatter's locale , en_US_POSIX will always be used.也就是说,如果有任何依赖于格式化程序locale内部代码,则将始终使用en_US_POSIX Second, the second block of code (the one that performs the actual swizzling) should be called exactly one time;其次,第二个代码块(执行实际 swizzling 的那个)应该被调用一次; look into wrapping it in a dispatch_once block to ensure it only runs once.考虑将它包装在dispatch_once块中以确保它只运行一次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM