How can I get SwiftUI to detect changes to a Dictionary?

Viewed 1992

How can I get SwiftUI to detect when the values in a Dictionary get changed?

class DictModel: ObservableObject {
    @Published var dict: [String: [String: Int]] = [:]
}

SwiftUI code

struct TestPublishedDidSet: View {
    @ObservedObject var vm = DictModel()

    var body: some View {
        VStack {
            Button("Assign") { self.vm.dict = ["Key1": ["Some value": 1]] }
            Button("Modify") { self.vm.dict["Key2"] = ["Some new value": 2] }
            Divider()
           ForEach(Array(self.vm.dict.keys), id: \.self) { key in
              VStack {
                 Text("\(key)")
                 ForEach(Array(self.vm.dict[key].keys), id: \.self) { key in
                    Text("\(key): \(self.vm.dict[key][key])")
                 }
              }
           }
        }
    }
}

I assume that it may be necessary to create a custom Dictionary class that sends and update() message when any key value is added or changed. Any idea on how that would be done. Note that the updates are performed by a background thread using a DispatchQueue.main.async{} call.

EDIT: - this does actually work - I must have been doing something else wrong.

1 Answers

The following example works, updates UI, for both use-cases: assign & modify.

Tested with Xcode 11.4 / iOS 13.4

class DictModel: ObservableObject {
    @Published var dict: [String: String] = [:]
}

struct TestPublishedDidSet: View {
    @ObservedObject var vm = DictModel()

    var body: some View {
        VStack {
            Button("Assign") { self.vm.dict = ["Key1": "Some value"] }
            Button("Modify") { self.vm.dict["Key2"] = "Some new value" }
            Divider()
           ForEach(Array(self.vm.dict.keys), id: \.self) { key in
              Text("\(self.vm.dict[key]!)...")
           }
        }
    }
}
Related