我通常使用 "faulting"
或lazy initialization
iOS 中处理大对象时的模式。
每当一个类有一个指向“胖”对象的属性时,我都会创建一个自定义 getter 来检查 iVar
是否有效。是 nil
。如果是,它会创建胖对象并返回它。如果不是,它只返回“胖”对象。
此属性的容器还订阅内存警告,当收到警告时,它会设置 iVar
至nil
,减少内存占用。如您所见,这与 Core Data 中的故障非常相似。
我正在尝试在 Swift 中重现这一点,但到目前为止还没有找到一个体面且优雅的解决方案。
a) 第一次尝试:惰性存储属性
这不起作用,因为如果我将属性设置为零,它将永远保持为零。 “魔法”仅在您第一次访问该属性时发生:
struct FatThing{
// I represent something big, which might have to be
// "faulted" (set to nil) when a memory warning
// is received
var bigThing = "I'm fat"
}
class Container {
lazy var fat: FatThing? = FatThing()
}
var c = Container()
c.fat
c.fat = nil
c.fat // returns nil
b) 第二次尝试:带有观察者的存储属性
由于缺少 get 观察者,这也会失败。我需要一个willGet
和didGet
,不仅仅是 willSet
和didSet
.
到底为什么没有 get 观察者?这个叫观察者的半支持的东西有什么用?
c) 第三次尝试:具有存储的辅助属性的计算属性
这是迄今为止我找到的唯一可行的选择,但它像狒狒的屁股一样丑陋!
struct FatThing{
// I represent something big, which might have to be
// "faulted" (set to nil) when a memory warning
// is received
var bigThing = "I'm fat"
}
class Container {
private var _fat : FatThing? // having this extra and exposed var kills my inner child
var fat: FatThing? {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat
}
set{
_fat = newValue
}
}
}
var c = Container()
c.fat
c.fat = nil
c.fat // returns FatThing
让我的代码看起来更简单、更短,就这么多了......
有没有一种简单而优雅的方法来实现这一点?在像 iOS 这样的内存匮乏的环境中,这并不是什么奇怪的东西!
最佳答案
单独重写 getter 或 setter 的能力是 objective-c 的一个特性,而 swift 中没有对应的特性。
您可以选择的正确选择是“否”。 3、使用支持属性来存储脂肪数据和计算属性以使其可访问。我同意有一些样板代码,但这是获得您需要的东西的权衡。
但是,如果您经常使用该模式,那么您可以创建一个协议(protocol):
protocol Instantiable {
init()
}
并在您的FatThing
结构/类中实现它。接下来,创建一个包含样板代码的通用函数:
func lazyInitializer<T: Instantiable>(inout property: T?) -> T {
if property == nil {
property = T()
}
return property!
}
请注意,T
必须实现 Instantiable
- 允许您使用无参数构造函数创建实例。
最后,按如下方式使用:
private var _fat : FatThing? // having this extra and exposed var kills my inner child
var fat: FatThing? {
get { return lazyInitializer(&self._fat) }
set { _fat = newValue }
}
请注意,在您的代码中,您不必将 fat
计算机属性声明为可选 - 您可以确保在 get
实现中它始终不为零,所以更好的实现是:
var fat: FatThing {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat!
}
set{
_fat = newValue
}
}
关于ios - Swift 中的错误或 "lazy initialisation"模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26700635/