如果数组元素的属性发生更改,如何触发操作?

时间:2017-05-27 15:12:46

标签: arrays swift key-value-observing access-control

在Swift中,我有一个数据模型,它使用在表格视图中显示的项目数组 数据模型可以随时由各种源更改,我想在更改时重新加载表视图。

如果项目数组本身被更改,这非常简单,例如通过为数据模型的数组属性分配一个新数组:setter可以触发重新加载,例如由KVO。
但是,如果仅通过更改其中一个属性来更改数组元素(项目),则表视图重新加载必须由项目属性的setter触发。 如果每个项目都有一个对存储项目数组的数据模型的引用,则可以这样做:使用此引用,可以向数据模型通知项目的更改,并触发重新加载表视图。但是,如果数组元素引用了它的数组,我认为这不是一个好的编程风格。

另一种方法是,数组元素(项目)只能由数据模型本身更改。在这种情况下,项目属性的setter只能用于数据模型。 实现此目的的一种方法是在同一文件中定义用户模型类和项类,并将项的属性设置器声明为fileprivate。然后,只有数据模型才能更改项目的属性。 但是,由于这个原因,在一个文件中定义两个类似乎不是很优雅。

有没有更简单的方法来处理这种情况?

1 个答案:

答案 0 :(得分:3)

另一个解决方案是使用协议编写您自己的简单观察系统。优点是它可以使所有内容更加松散耦合,并且可以轻松扩展以供将来使用:

class MyElement {
    var property = "Test" {
        didSet {
            guard property != oldValue else { return }
            for observer in observers {
                observer.didChangeProperty(element: self)
            }
        }
    }

    var observers: [MyElementObserver] = []
}

protocol MyElementObserver {
    func didChangeProperty(element: MyElement)
}

extension MyElementObserver {
    func didChangeProperty(element: MyElement) {}
}

然后,您可以使您的视图符合此协议,并处理将其自身添加到每个元素的observers数组,或者您可以使用可能更清晰的路由并制定MyDataModelObserver协议,然后让您的数据模型观察其元素并将这些通知传递给观察者(即视图)。