在Swift中重新初始化一个懒惰的初始化variables

我有一个variables,初始化为:

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

问题是,在某些时候,我需要重置这个aClientvariables,以便它可以在ClinetSession.shared()更改时再次初始化。 但是,如果我把课程设置为可选的Clinet? ,当我尝试将它设置nil时,LLVM会给我一个错误。 如果我使用aClient = Clinet(ClinetSession.shared())在代码中的某处重置它,它将以EXEC_BAD_ACCESS结束。

有没有办法可以使用lazy和被允许重置自己?

谢谢!

懒惰是明确的一次性只有初始化。 您要采用的模型可能只是一个按需初始化模型:

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

现在每当_aClient nil ,它将被初始化并返回。 可以通过设置_aClient = nil来重新初始化

这个解决scheme不再适用于Swift 4!

相反,我build议你使用@ PBosman的解决scheme

下面的行为是一个错误,在Swift bug SR-5172 (已经在2017-07-14已经被parsing, PR#10,911已经被parsing)中描述,并且很明显,这种行为从来没有故意。

Swift 3的解决scheme出于历史原因,但由于这是一个漏洞利用, 我build议你要这样做:


我不确定这是什么时候添加的,但是从Swift 3开始 ,您可以简单地将属性设置为nil-able:

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

现在,下一次将它设置为nil之后调用aClient,它将被重新初始化。


请注意,尽pipe现在在技术上是可选的,但是每次尝试读取它时,都会保证具有运行时值。 这就是我使用的原因! 在这里,因为它总是一个安全的调用,永远不会被 nil ,但它可以设置 nil

编辑:根据Ben Leggiero的回答,懒惰的变数可以在Swift 3中无效。

晚会很晚,甚至不知道这是否与Swift 3相关,但是这里有。 David的回答是好的,但是如果你想创造许多懒惰的可变的variables,你将不得不编写一个相当庞大的代码块。 我正在尝试创build一个封装了这个行为的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() 

有些事情我不喜欢,但是不知道如何改进:

  • 你必须传递一个构造函数给初始化器,这看起来很丑。 不过,它的优势在于,您可以精确指定如何创build新对象。
  • 每当你想使用它时,调用get()属性是非常糟糕的。 如果这是一个计算的属性,而不是一个函数,但是计算的属性不能改变,那会更好一些。
  • 为了消除调用get()的需要,你必须扩展每个你想使用的types和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 } }