静态计算变量被多次实例化

Static computed variable gets instantiated more than once

我有一个日期格式化程序,我试图在 UITableViewCell 子 class 中创建一个单例,所以我创建了一个计算 属性 ,如下所示:

private static var dateFormatter: NSDateFormatter {
    print("here here")
    let formatter = NSDateFormatter()
    formatter.dateFormat = "EEEE h a"
    return formatter
}

问题是我不止一次看到打印语句,这意味着它被创建了不止一次。我找到了其他方法来执行此操作(例如放入外部 class 或 class 方法),但我很想了解这里发生了什么。有什么想法吗?

您的静态变量不是单例,它只是一个 class 创建和 returns 日期格式化程序实例的方法。

检查这些关于如何创建真正的单胞胎的答案:Using a dispatch_once singleton model in Swift

你的代码片段相当于一个 get-only 属性,基本上它是一样的:

private static var dateFormatter: NSDateFormatter {
    get {
        print("here here")
        let formatter = NSDateFormatter()
        formatter.dateFormat = "EEEE h a"
        return formatter
    }
}

如果你只想要它 运行 一旦你应该像定义一个惰性的那样定义它 属性:

private static var dateFormatter: NSDateFormatter = {
    print("here here")
    let formatter = NSDateFormatter()
    formatter.dateFormat = "EEEE h a"
    return formatter
}()

当我试图弄清楚 Swift 中包含 =() 的静态计算 属性 之间的区别时,我花了一段时间才找到这个问题和一个没有。 @dan 很好地解释了应该如何确保静态 属性 只计算一次,但在我自己的实验中,我想出了以下示例,它帮助我形象化了两种用途之间的差异。

static var foo: String {
    print("computing foo")
    return "foo"
}

static var bar: String = {
    print("computing bar")
    return "bar"
}()

for _ in 1...3 {
    print(Class.foo)
    print(Class.bar)
}

最终结果是:

computing foo
foo
computing bar
bar
computing foo
foo
bar
computing foo
foo
bar

foo 具有静态 属性 的优点,包括与类型关联而不是特定实例,并且不能被子类覆盖。然而,bar 更进一步,确保 属性 仅计算一次。

静态属性可以是 computed,也可以是 lazy,这取决于你如何写出来。

- computed 表示每次调用它们的值都会重新计算:

private static var dateFormatter: NSDateFormatter {
    print("here here") // prints each time dateFormatter its called
    let formatter = NSDateFormatter()
    formatter.dateFormat = "EEEE h a"
    return formatter
}

- lazy 表示它们的值将被计算一次并且仅在第一次被调用时:

private static var dateFormatter: NSDateFormatter = {
    print("here here") // prints only one time, when called first time
    let formatter = NSDateFormatter()
    formatter.dateFormat = "EEEE h a"
    return formatter
}()