Ios 断层或;“惰性初始化”;雨燕图案
在处理大型对象时,我通常在iOS中使用Ios 断层或;“惰性初始化”;雨燕图案,ios,swift,instance-variables,lazy-initialization,Ios,Swift,Instance Variables,Lazy Initialization,在处理大型对象时,我通常在iOS中使用“faulting”或惰性初始化模式 每当一个类有一个指向“fat”对象的属性时,我都会创建一个自定义getter来检查iVar是否为nil。如果是,它将创建fat对象并返回它。如果不是,它只返回“fat”对象 此属性的容器还订阅内存警告,当收到警告时,它会将iVar设置为nil,从而减少内存占用。正如您所看到的,这与核心数据中的错误非常相似 我试图在Swift中重现这一点,但到目前为止还没有找到一个像样而优雅的解决方案 a)第一次尝试:延迟存储属性 这不起
“faulting”
或惰性初始化
模式
每当一个类有一个指向“fat”对象的属性时,我都会创建一个自定义getter来检查iVar
是否为nil
。如果是,它将创建fat对象并返回它。如果不是,它只返回“fat”对象
此属性的容器还订阅内存警告,当收到警告时,它会将iVar
设置为nil
,从而减少内存占用。正如您所看到的,这与核心数据中的错误非常相似
我试图在Swift中重现这一点,但到目前为止还没有找到一个像样而优雅的解决方案
a)第一次尝试:延迟存储属性
这不起作用,因为如果我将属性设置为nil,它将永远保持为nil。“魔法”仅在您第一次访问该属性时发生:
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
究竟为什么没有服务器?这个被称为观察者的半背东西有什么用
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,使用backing属性存储fat数据,使用computed属性使其可访问。我同意有一些样板代码,但这是获得您需要的东西的权衡 但是,如果您经常使用该模式,则可以创建协议:
protocol Instantiable {
init()
}
并在FatThing
struct/class中实现它。接下来,创建一个包含样板代码的通用函数:
func lazyInitializer<T: Instantiable>(inout property: T?) -> T {
if property == nil {
property = T()
}
return property!
}
请注意,在您的代码中,您不必将
fat
计算机属性声明为可选-您可以在get
实现中确保它始终不是零,因此更好的实现是:
var fat: FatThing {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat!
}
set{
_fat = newValue
}
}
var fat: FatThing {
get{
if _fat == nil {
_fat = FatThing()
}
return _fat!
}
set{
_fat = newValue
}
}