我有一个初始化为的变量:
lazy var aClient:Clinet = {
var _aClient = Clinet(ClinetSession.shared())
_aClient.delegate = self
return _aClient
}()
Run Code Online (Sandbox Code Playgroud)
问题是,在某些时候,我需要重置此aClient
变量,以便它可以在ClinetSession.shared()
更改时再次初始化.但是如果我将类设置为可选Clinet?
,当我尝试将其设置为时,LLVM会给我一个错误nil
.如果我只是在代码中的某处使用aClient = Clinet(ClinetSession.shared())
它重置它,它将最终得到EXEC_BAD_ACCESS
.
有没有办法可以使用lazy
并被允许重置自己?
谢谢!
Dav*_*rry 86
lazy明确表示只进行一次初始化.您要采用的模型可能只是初始化按需模型:
var aClient:Client {
if(_aClient == nil) {
_aClient = Client(ClientSession.shared())
}
return _aClient!
}
var _aClient:Client?
Run Code Online (Sandbox Code Playgroud)
现在,只要_aClient
在nil
,它会被初始化并返回.它可以通过设置重新初始化_aClient = nil
Ben*_*ero 42
因为lazy
在Swift 4 中改变了行为,我写了几个struct
给出非常具体的行为,这些行为在语言版本之间永远不会改变.这些是在GitHub上的ResettableLazy
许可证下:https://github.com/BenLeggiero/Swift-Lazy-Patterns
lazy var aClient:Client! = {
var _aClient = Client(ClinetSession.shared())
_aClient.delegate = self
return _aClient
}()
// ...
aClient = nil
以下是与此问题相关的问题,它为您提供了一种方法来延迟初始化值,缓存该值并将其销毁,以便以后可以进行延迟重新初始化:
@ResettableLazy
var myLazyString = "Hello, lazy!"
print(myLazyString) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString) // Just returns the value "Hello, lazy!"
_myLazyString.clear()
print(myLazyString) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString) // Just returns the value "Hello, lazy!"
myLazyString = "Overwritten"
print(myLazyString) // Just returns the value "Overwritten"
_myLazyString.clear()
print(myLazyString.wrappedValue) // Initializes, caches, and returns the value "Hello, lazy!"
Run Code Online (Sandbox Code Playgroud)
这可以这样使用:
Hello, lazy!
Hello, lazy!
Hello, lazy!
Hello, lazy!
Overwritten
Hello, lazy!
Run Code Online (Sandbox Code Playgroud)
这将打印:
func makeLazyString() -> String {
print("Initializer side-effect")
return "Hello, lazy!"
}
@ResettableLazy(initializer: makeLazyString)
var myLazyString: String
print(myLazyString) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString) // Just returns the value "Hello, lazy!"
_myLazyString.clear()
print(myLazyString) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString) // Just returns the value "Hello, lazy!"
myLazyString = "Overwritten"
print(myLazyString) // Just returns the value "Overwritten"
_myLazyString.clear()
print(myLazyString.wrappedValue) // Initializes, caches, and returns the value "Hello, lazy!"
Run Code Online (Sandbox Code Playgroud)
这种模式的一个主要优点是它可以存储nil
得很好,而其他模式在这里并没有真正定义的行为:
var myLazyString = ResettableLazy<String>() {
print("Initializer side-effect")
return "Hello, lazy!"
}
print(myLazyString.wrappedValue) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString.wrappedValue) // Just returns the value "Hello, lazy!"
myLazyString.clear()
print(myLazyString.wrappedValue) // Initializes, caches, and returns the value "Hello, lazy!"
print(myLazyString.wrappedValue) // Just returns the value "Hello, lazy!"
myLazyString.wrappedValue = "Overwritten"
print(myLazyString.wrappedValue) // Just returns the value "Overwritten"
_myLazyString.clear()
print(myLazyString.wrappedValue) // Initializes, caches, and returns the value "Hello, lazy!"
Run Code Online (Sandbox Code Playgroud)
这将打印:
Initializer side-effect
Hello, lazy!
Hello, lazy!
Initializer side-effect
Hello, lazy!
Hello, lazy!
Overwritten
Initializer side-effect
Hello, lazy!
Run Code Online (Sandbox Code Playgroud)
相反,我建议您使用上面列出的解决方案之一,或@ PBosman的解决方案
以下行为是一个错误,在Swift bug SR-5172中描述(已经在2017-07-14与PR#10,911一起解决),很明显这种行为从来都不是故意的.
Swift 3的解决方案由于历史原因而在下面,但是因为它是一个在Swift 3.2+中不起作用的漏洞利用,我建议你不要这样做:
我不确定这个添加的确切时间,但是从Swift 3开始,你可以简单地使属性为nil-able: 现在,下次在设置之后调用aClient时,它将被重新初始化.---请注意,虽然现在技术上是可选的,但每次尝试读取它时,都保证具有运行时值.这就是为什么我使用,在这里,因为它始终是一个安全的通话,绝不会被读为,但它可以被设置到.
!
nil
nil
lazy
struct
编辑:根据Ben Leggiero的回答,懒惰的变量可以nil
在Swift 3中编辑.编辑2:看起来像懒惰的变量就不复存在nil
了.
非常迟到了,甚至不会知道这将是斯威夫特3有关,但在这里不用.大卫的答案很好,但如果你想创建许多懒惰的无法变量,你将不得不写一个相当庞大的代码块.我正在尝试创建一个封装此行为的ADT.这是我到目前为止所得到的:
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 }
}
Run Code Online (Sandbox Code Playgroud)
然后,您将声明并使用如下属性:
var aClient = ClearableLazy(Client.init)
aClient.get().delegate = self
aClient.clear()
Run Code Online (Sandbox Code Playgroud)
有些事情我还不喜欢这个,但不知道如何改进:
get()
每次想要使用它时都要打电话是很糟糕的.如果这是一个计算属性而不是一个函数,那会好一点,但计算属性不能变异.get()
,你必须扩展你想要使用它的每个类型的初始化器ClearableLazy
.如果有人想从这里捡起它,那就太棒了.
这允许将属性设置nil
为强制重新初始化:
private var _recordedFileURL: NSURL!
/// Location of the recorded file
private var recordedFileURL: NSURL! {
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
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
22104 次 |
最近记录: |