Повторно инициализировать ленивую инициализированную переменную в Swift

У меня есть переменная, которая инициализируется как:

lazy var aClient:Clinet = { var _aClient = Clinet(ClinetSession.shared()) _aClient.delegate = self return _aClient }() 

Проблема в том, что в какой-то момент мне нужно сбросить эту переменную aClient чтобы она могла снова инициализироваться при изменении ClinetSession.shared() . Но если я установил класс в дополнительный Clinet? , LLVM даст мне ошибку, когда я попытаюсь установить ее на nil . Если я просто aClient = Clinet(ClinetSession.shared()) его где-нибудь в коде, используя aClient = Clinet(ClinetSession.shared()) , он будет в конечном итоге с EXEC_BAD_ACCESS .

Есть ли способ, который может использовать lazy и иметь возможность перезагружать себя?

Благодаря!

lazy явно для одноразовой инициализации. Модель, которую вы хотите принять, вероятно, просто модель инициализации по требованию:

 var aClient:Client { get { if(_aClient == nil) { _aClient = Client(ClientSession.shared()) } return _aClient! } } var _aClient:Client? 

Теперь, когда _aClient равен nil , он будет инициализирован и возвращен. Его можно _aClient = nil инициализировать, установив _aClient = nil

Это решение больше не работает в Swift 4!

Вместо этого я рекомендую вам использовать решение @ PBosman

Приведенное ниже поведение было ошибкой, описанной в ошибке Swift SR-5172 (которая была разрешена по состоянию на 2017-07-14 с PR # 10,911 ), и ясно, что это поведение никогда не было преднамеренным.

Решение для Swift 3 приведено по историческим причинам, но поскольку это уязвимость, я рекомендую вам не делать этого:


Я не уверен, когда это было добавлено, но с Swift 3 вы можете просто сделать свойство nil-able:

 lazy var aClient:Client! = { var _aClient = Client(ClinetSession.shared()) _aClient.delegate = self return _aClient }() // ... aClient = nil 

Теперь, в следующий раз, когда вы вызываете aClient после установки его в nil , он будет повторно инициализирован.


Обратите внимание, что, хотя в настоящее время это технически необязательно, каждый раз, когда вы пытаетесь его прочитать, у него гарантировано время выполнения. Вот почему я использую ! , здесь, потому что он всегда является безопасным вызовом и никогда не будет считан как nil , но его можно установить на nil .

РЕДАКТИРОВАТЬ: В соответствии с ответом Бена Леггьеро, ленивые вары могут быть полезны в Swift 3.

Очень поздно вечеринке, и даже не уверен, что это будет актуально в Swift 3, но здесь идет. Ответ Дэвида хорош, но если вы хотите создать много ленивых ноль-способных варов, вам придется написать довольно здоровенный блок кода. Я пытаюсь создать ADT, который инкапсулирует это поведение. Вот что у меня до сих пор:

 struct ClearableLazy<T> { struct ClearableLazy<T> { private var t: T! private var constructor: () -> T init(_ constructor: () -> T) { self.constructor = constructor } mutating func get() -> T { if t == nil { t = constructor() } return t } mutating func clear() { t = nil } } 

Затем вы объявляете и используете такие свойства:

 var aClient = ClearableLazy(Client.init) aClient.get().delegate = self aClient.clear() 

Есть вещи, которые мне пока не нравятся, но не знаю, как улучшить:

  • Вы должны передать конструктор инициализатору, который выглядит уродливым. Преимущество состоит в том, что вы можете точно указать, как должны быть созданы новые объекты.
  • Вызов get() на свойство каждый раз, когда вы хотите его использовать, ужасен. Было бы немного лучше, если бы это было вычисленное свойство, а не функция, но вычисленные свойства не могут быть мутирующими.
  • Чтобы устранить необходимость вызова get() , вам необходимо расширить каждый тип, который вы хотите использовать для инициализаторов для ClearableLazy .

Если кто-то чувствует, что он подбирает это отсюда, это было бы потрясающе.

Это позволяет установить свойство nil для принудительной инициализации:

 private var _recordedFileURL: NSURL! /// Location of the recorded file private var recordedFileURL: NSURL! { get { if _recordedFileURL == nil { let file = "recording\(arc4random()).caf" let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(file) NSLog("FDSoundActivatedRecorder opened recording file: %@", url) _recordedFileURL = url } return _recordedFileURL } } 
  • Необходимы ли файлы dSYM во время разработки?
  • Есть ли какие-либо коммерческие дополнения по программированию для Mac и iOS Cocoa / Objective C?
  • Дженкинс: где файл login.keychain в папке / Users / * name * / Library / Keychains?
  • Как я могу запустить приложение iphone для запуска из моего приложения mac
  • Неверное решение GCD производителя-потребителя Apple doc?
  • Перенос файлов из приложения iOS в Mac?
  • Перемещение файлов в настоящую папку в Xcode
  • Программное создание NSView в какао
  • Обрезка в Swift
  • Лучшие практики и предложения для опытных разработчиков iOS, начинающих разработку OS X?
  • Xcode Server ibtool Build Failures
  • Давайте будем гением компьютера.