内存访问与结构和观察者模式冲突

时间:2019-11-21 21:10:15

标签: swift memory model-view-controller memory-management observer-pattern

我正在Struct模型对象上实现观察者设计模式。我的想法是,我将沿着一个UIViewController链传递我的模型,并且随着每个控制器的修改,以前的控制器也将随着对象的更改而更新。

我知道可以通过使用class而不是struct并通过引用直接修改对象来解决此问题,但是我试图学习有关使用structs的更多信息

struct ModelObject {
    var data: Int = 0 {
        didSet {
            self.notify()
        }
    }
    private var observers = [ModelObserver]()

    mutating func attachObserver(_ observer: ModelObserver){
        self.observers.append(observer)
    }

    private func notify(){
        for observer in observers {
            observer.modelUpdated(self)
        }
    }
}

protocol ModelObserver {
    var observerID: Int { get }
    func modelUpdated(_ model: ModelObject)
}

class MyViewController : UIViewController, ModelObserver {
    var observerID: Int = 1
    var model = ModelObject()

    override func viewDidLoad() {
        self.model.attachObserver(self)
        self.model.data = 777
    }

    func modelUpdated(_ model: ModelObject) {
        print("received updated model")
        self.model = model //<-- problem code
    }
}

简而言之,当data发生变化时,我的模型对象通过调用notify()通知任何观察者。

我现在的问题是内存访问:data设置为777时,self.model被独占访问,并且当它调用notify时又调用{{1} },最后modelUpdated,我们得到一个错误:

self.model = model

如何解决此内存访问问题?

1 个答案:

答案 0 :(得分:1)

如果您正在观察“事物”,则该“事物”具有身份。您正在观察这件事。您无法观察到数字4。它没有身份。每4个与其他4个相同。结构是值。他们没有身份。您不应像观察Int那样尝试观察它们(Int实际上是Swift中的结构)。

每次将结构传递给函数时,都会复制该结构。因此,当您说self.model = model时,是在说“制作模型的副本并将其分配给此属性”。但是您仍然处于排他性访问块中,因为每次修改结构时,该结构也会产生一个副本。

如果您打算观察ModelObject,则ModelObject应该是引用类型,类。然后,您可以谈论“此特定ModelObject”,而不是“包含这些值的ModelObject,并且与包含相同值的任何其他ModelObject都没有区别。”