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

问题描述 投票:1回答:1

我正在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时又调用了modelUpdated并最终调用self.model = model时,我们得到了一个错误:

Simultaneous accesses to 0x7fd8ee401168, but modification requires exclusive access.

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

swift memory model-view-controller memory-management observer-pattern
1个回答
1
投票

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

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

如果要观察ModelObject,则ModelObject应该是引用类型,即类。然后,您可以谈论“此特定ModelObject”,而不是“包含这些值的ModelObject,并且与包含相同值的任何其他ModelObject都没有区别。”
© www.soinside.com 2019 - 2024. All rights reserved.