我有一个数据管理器,它封装了对象的集合。我想听听该管理器中的更改以及集合对象中的更改。我想出了使用PassthroughSubject
和sink
的解决方案,但是我对Combine还是很陌生,想知道它是否正确,并且有更好的方法做到这一点。
import Combine
class Item {
var data = false {
didSet {
self.subject.send()
}
}
let subject = PassthroughSubject<Void, Never>()
}
class DataManager {
private(set) var items = [Item]() {
didSet {
self.subject.send()
}
}
let subject = PassthroughSubject<Void, Never>()
func addItem(_ item: Item) {
self.items.append(item)
item.subject.sink { [weak self] in
self?.subject.send()
}
}
}
var item = Item()
var manager = DataManager()
manager.subject.sink {
print("Received Update")
}
manager.addItem(item) // Received Update
item.data = false // Received Update
item.data = true // Received Update
答案 0 :(得分:0)
如果您可以控制存储的项目,则使它们的所有结构都可以使用。数组是结构,因此更改后将触发didSet。数组内部的结构应更改数组的值,并使didSet触发该数组。类不会因为类的引用值永不变而发生变化。当前的立场是,除非有充分的理由使用类,否则应在类上使用结构。 Swift documentation了解更多信息。
另一种选择是做已经在做的事情,并使所有类都符合某种协议,例如BindableObject
,然后监视每个对象的didChange
。
当前,虽然从数组中删除项目时您没有处理取消。您应该将{{1}的subscribe
的{{1}}到每个元素的didChange
。然后取所得的DataManager
并将其添加到该项目下键入关键字的字典中。然后,从阵列中删除该项目后,您应该删除关联的didChange
,这将取消订阅。
答案 1 :(得分:0)
对于最新版本的SwiftUI
,我将objectWillChange.send
函数传递给@Published
数组中的每个项目。然后,对于每个项目的每个属性,我将在willSet
属性更改处理程序中调用更新处理程序。
这是一个例子:
import Combine
final class User {
let prepareForUpdate: (() -> Void)?
var name: String {
willSet {
prepareForUpdate?()
}
}
init(prepareForUpdate: (() -> Void)? = nil, name: String) {
self.prepareForUpdate = prepareForUpdate
self.name = name
}
}
final class UserStore: ObservableObject {
@Published var users: [User]
init(_ users: [User] = []) {
self.users = users
}
func addUser(name: String) {
// Pass in our objectWillChange.send to the User object to listen for updates
let user = User(prepareForUpdate: objectWillChange.send, name: name)
users.append(user)
return user
}
}
使用此方法,只要更改User
数组中的users
,视图就会更新。