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

Memory access conflict with structs and observer pattern

我正在 Struct 模型对象上实施 Observer 设计模式。我的想法是,我将我的模型沿着 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.

如何解决这个内存访问问题?

如果您正在观察 "a thing,",那么 "thing" 就有一个身份。这是你正在观察的一件特别的事情。你不能观察数字 4。它是一个值;它没有身份。每 4 个都与其他 4 个相同。结构是值。他们没有身份。您不应该尝试观察它们,就像您尝试观察 Int 一样(Int 实际上是 Swift 中的一个结构)。

每次将结构传递给函数时,都会生成该结构的副本。所以当你说 self.model = model 时,你说的是 "make a copy of model, and assign it to this property." 但是你仍然处于独占访问块中,因为每次修改结构时,它也会生成一个副本。

如果你的意思是观察ModelObject,那么ModelObject应该是一个引用类型,一个class。那么你可以谈论 "this particular ModelObject" 而不是 "a ModelObject that contains these values, and is indistinguishable from any other ModelObject which contains the same values."