静态计算变量不止一次被实例化

Jul*_* B. 9 static nsdate nsdateformatter ios swift

我有一个日期格式化程序,我正在尝试创建一个UITableViewCell子类中的单例,所以我创建了一个这样的计算属性:

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

问题是我不止一次看到print语句,这意味着它不止一次被创建.我已经找到了其他方法(比如加入外部课程或类课程),但我很想知道这里发生了什么.有任何想法吗?

dan*_*dan 17

您的代码段相当于只获取属性,基本上它与以下内容相同:

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

如果你只想运行一次,你应该像定义一个惰性属性一样定义它:

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


小智 7

当我试图找出 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)
}
Run Code Online (Sandbox Code Playgroud)

最终结果是:

computing foo
foo
computing bar
bar
computing foo
foo
bar
computing foo
foo
bar
Run Code Online (Sandbox Code Playgroud)

foo具有静态属性的优点,包括与类型而不是特定实例的关联以及不能被子类覆盖。bar但是,通过确保属性只计算一次,可以更进一步。