MVVM场景下SwiftUI List视图无法更新的问题求助
问题解决:SwiftUI添加行后列表不更新
核心问题在于你的ViewModel结构:@Published var itemContent = ItemContent()只会在itemContent本身被替换时触发UI更新,而itemContent内部的children数组变化,无法传递到ViewModel的发布流中,导致List感知不到数据变化。
解决方案一:转发ItemContent的变化事件
在ViewModel中订阅itemContent的objectWillChange事件,将其转发到自身的发布流,这样内部属性变化就能触发UI刷新:
extension ContentView { class ViewModel: ObservableObject { @Published var itemContent = ItemContent() @Published var selectedRows = Set<ContentRow>() private var cancellables = Set<AnyCancellable>() init() { // 订阅itemContent的内部变化,转发给ViewModel的发布流 itemContent.objectWillChange .sink { [weak self] _ in self?.objectWillChange.send() } .store(in: &cancellables) } func add() { let row = ContentRow() itemContent.children.append(row) } } }
解决方案二:简化数据结构(更推荐)
如果ItemContent仅作为children的容器,可以直接将children移到ViewModel中,减少嵌套层级,避免事件传递问题:
- 移除
ItemContent类 - 修改
ViewModel和ContentView:
// MARK: - views/ view model. struct ContentView: View { @StateObject var vm = ViewModel() var body: some View { NavigationStack { List(selection: $vm.selectedRows) { ForEach(vm.children, id: \.id) { row in RowView(row: row) } } .toolbar { ToolbarItem { Button("add", action: vm.add) } } } } } extension ContentView { class ViewModel: ObservableObject { @Published var children: [ContentRow] = [] @Published var selectedRows = Set<ContentRow>() func add() { let row = ContentRow() children.append(row) } } }
原理说明
SwiftUI的@Published对于引用类型(如ObservableObject实例),仅在引用本身改变时(比如给itemContent赋值新的ItemContent())才会触发更新。当你修改itemContent内部的children数组,itemContent的引用没有变化,因此ViewModel不会通知UI刷新。通过订阅转发或简化层级,就能让UI感知到内部数据的变化。
内容的提问来源于stack exchange,提问作者MatFetsch
相关产品推荐
相关产品推荐

