ios - Swift 中的错误或 "lazy initialisation"模式

标签 ios swift instance-variables lazy-initialization

我通常使用 "faulting"lazy initialization iOS 中处理大对象时的模式。

每当一个类有一个指向“胖”对象的属性时,我都会创建一个自定义 getter 来检查 iVar 是否有效。是 nil 。如果是,它会创建胖对象并返回它。如果不是,它只返回“胖”对象。

此属性的容器还订阅内存警告,当收到警告时,它会设置 iVarnil减少内存占用。如您所见,这与 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 观察者,这也会失败。我需要一个willGetdidGet ,不仅仅是 willSetdidSet .

到底为什么没有 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/

相关文章:

ios - swift 4 : Unexpectedly found nil while unwrapping an Optional value

ios - Swift Playgrounds 书架标题

ios - Swift CollectionView第一个单元格添加用户按钮,并从图像数组加载其他单元格

ios - Twitter 工具包未在时间轴中显示视频

ruby Rspec : Testing instance variables without adding an accessor to source

python - 当我们实例化一个对象时,Python中的类变量是否表现为实例变量?

ios - skscene 中的 skscene

ios - 如何始终在 Obj c 中看到 Tableview 的滚动条?

ios - 安排任务在 phonegap ios 中的特定时间运行?

java - 术语:实例变量的单字 Java 术语?