在 Swift 中实现惰性属性并将其设置为 nil
Implementing a lazy property and setting it to nil in Swift
我想实现一个惰性属性,这样它只有在第一次被访问时才会有值。但是后来我想把它设置为nil
来释放内存资源。然后,当应用程序再次尝试访问它时,它将被重新创建,因此当它即将被访问时,它不应该是 nil
。
我翻阅了 Swift 编程书籍并阅读了惰性属性,但是那里的信息很少,没有这个用例的例子。
我看到 this answer by Rudolf Adamkovic 并实现了该格式,但该项目无法在 Xcode 6.2 beta 3 中编译:Use of undeclared type 'String'
let model = MyModelClass()
lazy var recentlyAdded: [String] = self.recents() //error here
func recents() -> [String] {
return self.model.recentlyAdded()
}
我也尝试过这种格式,但它也无法编译并出现相同的编译时错误。
lazy var recentlyAdded: [String] = self.model.recentlyAdded()
实现这种惰性属性的正确方法是什么?
是这样的吗?
struct S {
var _actualVar: String? = nil
var lazyVar: String? {
mutating get {
if _actualVar == nil {
_actualVar = someCalc()
}
return _actualVar
}
set(newVar) {
_actualVar = newVar
}
}
}
var s = S()
s.lazyVar // someCalc will be called
s.lazyVar // but not here
s.lazyVar = nil
s.lazyVar // but it'll be called again here
请注意,与惰性 属性 一样,这确实需要使用 lazyVar
的 get
版本,您的 s
变量仍然必须声明为var
这可能有点令人惊讶。
我无法弄清楚这个问题。不过我解决了。
当我复制并粘贴你的代码时,我得到了同样的错误:
Use of undeclared type 'String'
我删除了它并重新输入了它(没有自动完成)并且它对我有用。
看起来像是 XCode 中的错误。
我找到了解决办法。您不能像在 Objective-C 中那样使用 Swift 中的 lazy
属性 来执行惰性实例化,至少不能使用 Swift 1-3。如果你尝试,它不会被实例化,直到它被第一次访问,但如果你稍后将它设置为nil
,当你再次访问它时它仍然是nil
。它只会延迟实例化一次,这不是我想要的。
要实现 'true' 惰性实例化,您需要计算 属性 以及常规 属性,两者都是 var
。我将常规 属性 称为 "backing" 属性。本质上,如果支持 属性 是 nil
,则检查计算的 属性,如果是,则创建它,然后 return 支持 属性。这是一个计算的 属性,因此它不会在内存中存储值,而后备 属性 会。当你想得到它的值时,访问计算的属性。当您希望将其值设置为 nil
时,请设置支持 属性.
Apple 在他们的核心数据模板中使用了这种技术。他们对两者使用相同的 属性 名称,但在支持 属性 之前放置了一个下划线,它模仿了来自 Objective-C.
的 iVar
像这样的东西就可以了:
var fetchedResultsController: NSFetchedResultsController {
get {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
_fetchedResultsController = NSFetchedResultsController(fetchRequest: ...)
return _fetchedResultsController!
}
set {
_fetchedResultsController = newValue
}
}
var _fetchedResultsController: NSFetchedResultsController? = nil
使用方法:
_fetchResultsController = nil
self.fetchResultsController.performFetch()
我只使用可选的符号 - 即一个问号来表示它可以为零。例如
var myVar:String?
我想实现一个惰性属性,这样它只有在第一次被访问时才会有值。但是后来我想把它设置为nil
来释放内存资源。然后,当应用程序再次尝试访问它时,它将被重新创建,因此当它即将被访问时,它不应该是 nil
。
我翻阅了 Swift 编程书籍并阅读了惰性属性,但是那里的信息很少,没有这个用例的例子。
我看到 this answer by Rudolf Adamkovic 并实现了该格式,但该项目无法在 Xcode 6.2 beta 3 中编译:Use of undeclared type 'String'
let model = MyModelClass()
lazy var recentlyAdded: [String] = self.recents() //error here
func recents() -> [String] {
return self.model.recentlyAdded()
}
我也尝试过这种格式,但它也无法编译并出现相同的编译时错误。
lazy var recentlyAdded: [String] = self.model.recentlyAdded()
实现这种惰性属性的正确方法是什么?
是这样的吗?
struct S {
var _actualVar: String? = nil
var lazyVar: String? {
mutating get {
if _actualVar == nil {
_actualVar = someCalc()
}
return _actualVar
}
set(newVar) {
_actualVar = newVar
}
}
}
var s = S()
s.lazyVar // someCalc will be called
s.lazyVar // but not here
s.lazyVar = nil
s.lazyVar // but it'll be called again here
请注意,与惰性 属性 一样,这确实需要使用 lazyVar
的 get
版本,您的 s
变量仍然必须声明为var
这可能有点令人惊讶。
我无法弄清楚这个问题。不过我解决了。
当我复制并粘贴你的代码时,我得到了同样的错误:
Use of undeclared type 'String'
我删除了它并重新输入了它(没有自动完成)并且它对我有用。
看起来像是 XCode 中的错误。
我找到了解决办法。您不能像在 Objective-C 中那样使用 Swift 中的 lazy
属性 来执行惰性实例化,至少不能使用 Swift 1-3。如果你尝试,它不会被实例化,直到它被第一次访问,但如果你稍后将它设置为nil
,当你再次访问它时它仍然是nil
。它只会延迟实例化一次,这不是我想要的。
要实现 'true' 惰性实例化,您需要计算 属性 以及常规 属性,两者都是 var
。我将常规 属性 称为 "backing" 属性。本质上,如果支持 属性 是 nil
,则检查计算的 属性,如果是,则创建它,然后 return 支持 属性。这是一个计算的 属性,因此它不会在内存中存储值,而后备 属性 会。当你想得到它的值时,访问计算的属性。当您希望将其值设置为 nil
时,请设置支持 属性.
Apple 在他们的核心数据模板中使用了这种技术。他们对两者使用相同的 属性 名称,但在支持 属性 之前放置了一个下划线,它模仿了来自 Objective-C.
的 iVar像这样的东西就可以了:
var fetchedResultsController: NSFetchedResultsController {
get {
if _fetchedResultsController != nil {
return _fetchedResultsController!
}
_fetchedResultsController = NSFetchedResultsController(fetchRequest: ...)
return _fetchedResultsController!
}
set {
_fetchedResultsController = newValue
}
}
var _fetchedResultsController: NSFetchedResultsController? = nil
使用方法:
_fetchResultsController = nil
self.fetchResultsController.performFetch()
我只使用可选的符号 - 即一个问号来表示它可以为零。例如
var myVar:String?