我想实现一个惰性属性,以便在第一次访问它之前它不会有值。但后来我想将其设置为nil
以释放内存资源。然后,当应用程序再次尝试访问它时,它将被重新创建,因此当它即将被访问时,它不应该是nil
。
我查看了Swift Programming书并阅读了懒惰属性,但是信息很少,没有这个用例的例子。
我看到this answer by Rudolf Adamkovic并实现了该格式,但该项目无法在Xcode 6.2 beta 3中编译:{{1}}
Use of undeclared type 'String'
我也尝试过这种格式,但它也无法使用相同的编译时错误进行编译。
let model = MyModelClass()
lazy var recentlyAdded: [String] = self.recents() //error here
func recents() -> [String] {
return self.model.recentlyAdded()
}
实现这种类型的惰性属性的正确方法是什么?
答案 0 :(得分:2)
这样的东西?
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
请注意,与惰性属性一样,这需要使用get
lazyVar
版s
,您的var
变量仍然需要使用{{1}}声明可能有点令人惊讶。
答案 1 :(得分:2)
我找到了解决方案。您不能像在Objective-C中那样使用Swift中的lazy
属性来执行延迟实例化,至少不能使用Swift 1-3。如果您尝试,它将在第一次访问之前不会被实例化,但如果您稍后将其设置为nil
,当您再次访问它时,它仍将是nil
。它只会被懒惰地实例化一次,这不是我想要的。
要实现'true'延迟实例化,您需要一个计算属性以及一个常规属性,var
。我将常规属性称为“支持”属性。基本上,如果支持属性为nil
,则检入computed属性,如果是,则创建它,然后返回该支持属性。这是一个计算属性,因此它不会在内存中存储值,而后备属性则会。当您希望获取其值时,请访问计算属性。如果要将其值设置为nil
,请设置后备属性。
Apple在其核心数据模板中使用此技术。它们对两者使用相同的属性名称,但在backing属性之前放置一个下划线,后者属性模仿来自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()
答案 2 :(得分:1)
我无法弄清楚这个问题。但我解决了。
当我复制你的代码并粘贴时,我得到了同样的错误:
Use of undeclared type 'String'
我删除了它并重新输入(没有自动完成),它对我有用。
看起来像是XCode中的一个错误。
答案 3 :(得分:0)
我只是使用可选符号 - 即一个问号表示它可以是零。例如
var myVar:String?