swift - 发布对可观察对象集合的更改

标签 swift swiftui combine

我在传播保存在数组中的 View 模型中的对象发生的更改时遇到问题。
我明白 @Published如果集合本身发生变化(例如,如果元素是 struct 而不是 class ),则集合会起作用。假设我需要将类保留为类。有没有办法将事件传播到 View ,以便它知道应该刷新它。
我一直在尝试所有讨厌的方法,比如实现 ObservableCollectionObservableArray但似乎没有任何效果。
下面是我正在努力解决的一个例子。
Toggle 正在更改具有所有 ObservableObject 的数组的内部元素一致性和 @Published注释,但仍然没有刷新文本。

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()
    }
}

最佳答案

您的方法的问题在于 文本支架 是一个类,它是引用类型,如果您更改其中的任何值,更改将不会反射(reflect)到数组,这就是 SwiftUI View 未更新的原因。
方法一:
您可以更改 文本支架 从类到结构,如果您更改结构中的任何值,则会创建一个新副本,您的数组将更改为您的 SwiftUI View 。
请尝试以下代码

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
    }
}
方法二:
更改值后,您必须手动告诉您的 View 模型 东西变了,请刷新。
Button("Toggle") {
     vm.texts[0].toggle()
     vm.objectWillChange.send()
}
希望能帮助你理解。

关于swift - 发布对可观察对象集合的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68103063/

相关文章:

swiftui - fatal error : @SceneStorage is only for use with SwiftUI App Lifecycle. : file SwiftUI, 第 0 行

ios - 表单中的选取器在SwiftUI中留下了领先的空间

xcode - SwiftUI Canvas 预览编译错误: Undefined symbols for architecture x86_64

swift - 从现有的 SwiftUI @States 派生绑定(bind)

ios - 尝试检索图像时出现 NSInvalidArgumentException

ios - 在显示 ViewController 之前热加载@IBOutlet?

Swift Combine 如何跳过一个事件

ios - 快速组合 : `first(_ n: Int)` equivalent to RxSwift `take(_ n: Int)` ?

ios - 在 Swift 中从 AppDelegate 获取 ViewController 的实例

arrays - 填充 UITableViewController