首页 > 解决方案 > 将更改发布到可观察对象的集合

问题描述

我在传播视图模型中保存在数组中的对象上发生的更改时遇到问题。

我知道,@Published如果集合本身发生变化(例如,如果元素struct不是class),集合将起作用。假设我需要将类保留为类。有没有办法将事件传播到视图,以便它知道应该刷新它。

我一直在尝试所有讨厌的方法,例如实施ObservableCollectionObservableArray但似乎没有任何效果。

下面是我正在努力解决的一个例子。ObservableObjectToggle 正在更改具有所有一致性和@Published注释但仍然没有刷新 Text的数组的内部元素。

import SwiftUI
import Combine

struct ContentView: View {
    @StateObject var vm = ViewModel()
    
    var body: some View {
        Text(vm.texts.first!.text)
            .padding()
        
        Button("Toggle") {
            vm.texts.first?.toggle()
        }
    }
}

class ViewModel: ObservableObject {
    @Published var texts: [TextHolder] = [.init(), .init()]
}

class TextHolder: ObservableObject {
    @Published var text: String = ""
    
    func toggle() {
        text = UUID().uuidString
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

标签: swiftswiftuicombine

解决方案


您的方法的问题是TextHolder是一个类,它是引用类型,如果您更改其中的任何值,更改将不会反映到数组,这就是 SwiftUI 视图未更新的原因。

方法一:

您可以将TextHolder从类更改为结构,如果您更改结构中的任何值,则会创建一个新副本,您的数组将获得更改为您的 SwiftUI 视图。

请尝试以下代码

struct ContentView: View {
    @StateObject var vm = ViewModel()
    
    var body: some View {
        Text(vm.texts.first!.text)
            .padding()
        
        Button("Toggle") {
            vm.texts[0].toggle()
        }
    }
}

class ViewModel: ObservableObject {
    @Published var texts: [TextHolder] = [.init(), .init()]
}

struct TextHolder {
    var text: String = ""
    
    mutating func toggle() {
        text = UUID().uuidString
    }
}

方法二:

更改值后,您必须手动告诉您的viewModel某些内容已更改,请刷新。

Button("Toggle") {
     vm.texts[0].toggle()
     vm.objectWillChange.send()
}

希望能帮助你理解。


推荐阅读