Вычисляются ли ленивые переменные в Swift более одного раза?

#swift

#swift #ленивая инициализация #вычисляемые свойства

Вопрос:

Вычисляются ли ленивые переменные в Swift более одного раза? У меня сложилось впечатление, что они заменили:

 if (instanceVariable) {
    return instanceVariable;
}

// set up variable that has not been initialized
  

Парадигма из Objective-C (ленивое создание экземпляра).

Это то, что они делают? По сути, вызывается только один раз, когда приложение запрашивает переменную в первый раз, а затем просто возвращает то, что было вычислено?

Или это вызывается каждый раз, как обычное вычисляемое свойство?

Причина, по которой я спрашиваю, заключается в том, что мне в основном нужно вычисляемое свойство в Swift, которое может обращаться к другим переменным экземпляра. Допустим, у меня есть переменная с именем «FullName», и она просто объединяет firstName и lastName . Как бы я это сделал в Swift? Похоже, что ленивые переменные — это единственный путь, как и в обычных вычисляемых переменных (не ленивых) Я не могу получить доступ к другим переменным экземпляра.

Итак, в основном:

Вызываются ли ленивые переменные в Swift более одного раза? Если да, то как мне создать вычисляемую переменную, которая может обращаться к переменным экземпляра? Если нет, если я хочу, чтобы переменная вычислялась только один раз по соображениям производительности, как мне это сделать?

Ответ №1:

lazy var s вычисляются только один раз, при первом их использовании. После этого они работают как обычная переменная.

Это легко протестировать на игровой площадке:

 class LazyExample {
    var firstName = "John"
    var lastName = "Smith"
    lazy var lazyFullName : String = {
        [unowned self] in
        return "(self.firstName) (self.lastName)"
    }()
}

let lazyInstance = LazyExample()

println(lazyInstance.lazyFullName)
// John Smith

lazyInstance.firstName = "Jane"

println(lazyInstance.lazyFullName)
// John Smith

lazyInstance.lazyFullName = "???"

println(lazyInstance.lazyFullName)
// ???
  

Если вы захотите пересчитать его позже, используйте вычисляемое свойство (с резервной переменной, если это дорого) — точно так же, как вы делали в Objective-C.

Комментарии:

1.в вашем коде нет ничего плохого… но это потенциально вводит в заблуждение, т. Е. если вы измените change firstName на «Jane» перед тем, как получить доступ lazyFullName , тогда будет напечатано «Jane Smith»

Ответ №2:

Нет, ленивые свойства инициализируются только один раз. Если вы установите новое значение или сбросите значение до нуля (для необязательных свойств), отложенный инициализатор не вызывается снова.

Я думаю, что вам нужно вычисляемое свойство — оно не поддерживается сохраненным свойством, поэтому оно не участвует в инициализации, и поэтому вы можете ссылаться на другие свойства экземпляра.

Почему вы говорите, что «обычные вычисляемые переменные (не ленивые) Я не могу получить доступ к другим переменным экземпляра»?

Комментарии:

1. 1. Что вы имеете в виду, что вычисляемое свойство не поддерживается сохраненным свойством? Разве полное имя не поддерживается FirstName, LastName? 2. Помимо того, что lazy инициализируется один раз, является ли основное различие между ними в том, что: для lazy, если вы задаете lazyFullName, вы просто устанавливаете его … но для computedLazyFullName, если вы его задаете, вам нужен какой-то механизм для правильного обновления сохраненных свойств FirstName, LastName?

Ответ №3:

Все остальные ответы верны, я просто хотел бы добавить, что Apple предупреждает о lazy переменных и параллелизме:

Если к свойству, помеченному модификатором lazy, обращаются несколько потоков одновременно, и свойство еще не было инициализировано, нет гарантии, что свойство будет инициализировано только один раз.

Ответ №4:

Ответы, в которых утверждается, что ленивый var может быть вычислен только один раз, неверны. Из документации по адресу https://docs.swift.org/swift-book/LanguageGuide/Properties.html указано следующее:

Если к свойству, помеченному модификатором lazy, обращаются несколько потоков одновременно, и свойство еще не было инициализировано, нет гарантии, что свойство будет инициализировано только один раз.

Также, пожалуйста, посмотрите этот доклад: https://developer.apple.com/videos/play/wwdc2016/720 /. Примерно в 17:00 появляется следующий экран:

введите описание изображения здесь

Этот доклад дает вам больше информации о многопоточности, я рекомендую вам посмотреть его!