Статическая вычисляемая переменная создается несколько раз

у меня есть форматер даты, который я пытаюсь создать как синглтон в UITableViewCell подкласс, поэтому я создал вычисляемое свойство такой:

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

проблема в том, что я вижу оператор print более одного раза, что означает, что он создается более одного раза. Я нашел другие способы сделать это (например, ввести внешний класс или метод класса), но я хотел бы понять, что здесь происходит. Есть идеи?

3 ответов


ваш фрагмент эквивалентен свойству 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
}()

ваш статический var не является одноэлементным, это просто метод класса, который создает и возвращает экземпляр форматирования даты.

проверьте эти ответы о том, как создать настоящий sungleton:использование модели dispatch_once singleton в Swift


мне потребовалось некоторое время, чтобы найти этот вопрос при попытке выяснить разницу между статическим вычисляемым свойством в 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, однако, идет дальше, гарантируя, что свойство рассчитывается только один раз.