如何在 Swift class 扩展中创建 'static'?

How does one create a 'static' in a Swift class extension?

在这里的几个地方,有人建议在 NSDate 的扩展中使用计算的 属性 可能是通过 [=15= 获取日期的字符串版本的好方法],像这样:

extension NSDate {
    public var UTC : String {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        formatter.timeZone = NSTimeZone(abbreviation: "UTC")
        return formatter.stringFromDate(self)
    }
}

然而,分配一个 NSDateFormatter 是昂贵的,建议它们被创建一次并缓存。每次格式化日期时,上面的代码都会创建 NSDateFormatter,我想知道是否有一种方法可以在扩展中创建 NSDateFormatter once 以供重用?

显然,我可以在扩展之外创建它一次,但这似乎破坏了表征 类.

的封装

我想起了:https://xkcd.com/1179/ !!

您可以将静态成员添加到 class 扩展,就像在 classes 上一样。使用时需要在静态成员名称前加上 class 前缀,例如NSDate.dateFormatterUTC,即使您在同一个 class.

中使用它

这个有效:

extension NSDate {
    private static let dateFormatterUTC: NSDateFormatter = {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
        formatter.timeZone = NSTimeZone(abbreviation: "UTC")
        return formatter
    }()

    public var UTC : String {
        return NSDate.dateFormatterUTC.stringFromDate(self)
    }
}

仅仅使用私有常量也不是世界上最糟糕的事情:

private let dateFormatterUTC: NSDateFormatter = {
    let formatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
    formatter.timeZone = NSTimeZone(abbreviation: "UTC")
    return formatter
}()

extension NSDate {
    public var UTC : String {
        return dateFormatterUTC.stringFromDate(self)
    }
}

这并不比静态class成员差多少,因为Swift的privatefile-private,而不是类型-私有dateFormatterUTC 的这两个声明具有相同的作用域。即使在第一个示例中,NSDate.dateFormatterUTC 在声明它的整个文件中都可以访问。

我同意静态版本更可取,但仅出于风格原因:我喜欢它紧挨着使用它的东西缩进的方式。

作为, this approach assumes UTC will only ever be called from one thread. Although static let and global let are both thread-safe in Swift, the NSDateFormatter class is not! Looks like 。呸

不过,在提到单例的旁边加上线程安全警告总是好的。如果您确实想在多个线程中使用非线程安全的助手对象,请考虑在每次调用时创建一个新的助手,或者使用 NSThread.currentThread().threadDictionary 创建一个线程实例。在选择更复杂的线程本地选项之前,请务必进行一些分析以确保您确实解决了性能问题。