将数据更新传播到许多 ViewController 的传统架构是什么?

What is the conventional architecture to propagate data updates to many ViewControllers?

我正在开发一个具有三个视图的应用程序,这些视图同时显示在屏幕上并且共享相同的数据模型,一个 Swift 对象也有子对象。每个视图以不同的方式呈现数据,并为用户提供修改数据的方式,例如重新排序项目、adding/removing 项目等。此外,某些用户操作会触发对模型的异步更新,例如获取其他信息来自 API 的项目。我的目标是找到一种架构,使我能够通知每个视图的控制器数据更新,而无需在视图控制器之间强制通信。

解决这个问题的常规方法是什么?

常见的方法是订阅 NSNotification 以通知观察者已发生更新:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateData:) name:kAppDidUpdateDataNotification object:nil];

然后数据源可以向订阅者发送通知:

[[NSNotificationCenter defaultCenter] postNotificationName:kAppDidUpdateDataNotification
                                                    object:object];

另一种方法是共享数据源并使用 Key Value Observing on it. KVO lets you subscribe to updates on a keyPath (like a property on your data source). KVO is a little hairy—I recommend using a library that wraps it into something that supports blocks, or maybe consider a framework like ReactiveCocoa that has similar properties. Note that you can also observe changes to collections 和 KVO,如果你有,这很好。一个 NSMutableArray 的项目,多个 table 视图控制器显示它们,并且您想做一些事情,比如在从数组中删除对象时动画删除特定索引处的行。由于您提到重新订购和 adding/removing 项,这可能特别适合您。

将委托列表添加到您的数据模型,每当事件发生时,遍历列表并通知其委托。这是 Objective-C 委托模式的扩展,与通知中心的 addObserver/removeObserver.

非常相似
protocol DataModelDelegate {
    func dataModel(dataModel: DataModel, didFetchData data: String) // Or any other events
}

class DataModel {
    private delegates = [DataModelDelegates]()

    func addDelegate(delegate: DataModelDelegate) { delegates.append(delegate) }
    func removeDelegate(delegate: DataModelDelegate) { // Remove `delegate` from `delegates` }

    func dataFetched(data: String) { // Or any other events
        for d in delegates { d.dataModel(self, didFetchData: data) }
    }
}

...

class ViewController1: UIViewController, DataModelDelegate {
    private dataModel: DataModel!

    init(dataModel: DataModel) {
        ...
        self.dataModel = dataModel
        dataModel.addDelegate(self)
        ...
    }

    deinit {
        // Retain cycle without this!
        dataModel.removeDelegate(self)
    }

    func dataModel(dataModel: DataModel, didFetchData data: String) {
        // Update UI, etc
    }

}

通知中心也会做这项工作,但IMO通知中心应该只用于松散耦合的情况(即通知发送者和通知接收者彼此不了解);如果您的视图控制器对其共享数据模型有深入的了解,那么委托/多委托是更好的方法。

此外,根据您的问题,数据模型的生命周期可能独立于它的视图控制器(例如作为单例),或者由其中一个视图控制器管理。