如何在 RxSwift 中使可变字典可见

How can a mutable dictionary be made observable in RxSwift

我们希望使用可观察的字典来通知任何订阅者发生变化。到目前为止,这是作为 BehaviorRelay<[KeyType: ValueObjectType]>

实现的

现在我们需要 add/remove/change observable 中字典的值。我们尝试了以下方法(简单来说),但没有用:

let list = BehaviorRelay<[String: MyClassType]>.init([:])
let newElem = MyClassType()
list.value.updateValue(newElem, forKey: "anykey")

编译器抱怨:不能在不可变值上使用可变成员:'value' 是只获取 属性

下面的方法有效,但我发现它很麻烦,而且性能方面可能效率低下:

let list = BehaviorRelay<[String: MyClassType]>.init([:])
let newElem = MyClassType()
let newList = list.value
newList.updateValue(newElem, forKey: "anykey")
list.accept(newList)

UI 侧列表的典型订阅者是例如UITableView 或 UICollectionView。

有没有更好的方法来处理这个问题?

你的第二条路是要走的路。可以通过这样写来改进繁琐明智的:

let list = BehaviorRelay<[String: MyClassType]>.init(value: [:])
list.accept(list.value.merging(["anykey": MyClassType()]){ (_, new) in new })

如果必须多次执行此操作,以下扩展可以派上用场

extension Dictionary where Key == String, Value == MyClassType {
    static func + (lhs: [String : MyClassType], rhs: [String : MyClassType]) -> [String : MyClassType] {
        return lhs.merging(rhs) { (_, new) in new }
    }
}

现在你可以这样做了list.accept(list.value + ["anykey": MyClassType()])

请注意,如果右侧操作数的键也存在于左侧操作数中,则右侧值将覆盖左侧值。据我了解,这是您想要的行为。

您尝试的第一种方法也适用于 Variable。但是 Variable 现在被认为已弃用,取而代之的是 BehaviorRelayvalue 属性 of BehaviourRelay is only get.

在评论中与@JR 讨论后,可以为 BehaviorRelay 编写通用扩展,其中 ElementArray/ Dictionary

extension BehaviorRelay {
    func addElement<T>(element: T) where Element == [T] {
        accept(value + [element])
    }

    func removeElement<T>(element: T) where Element == [T], T: Equatable {
        accept(value.filter {[=12=] != element})
    }

    func addElement<T, U>(key: T, value: U) where Element == [T: U] {
        accept(self.value.merging([key: value]) { (_, new) in new })
    }
    func removeElemnent<T>(key: T) where Element == [T: Any] {
        accept(self.value.filter {dictElemnt in dictElemnt.key != key})
    }
}