@已发布属性未从嵌套视图模型更新视图-SwiftUI

@已发布属性未从嵌套视图模型更新视图-SwiftUI,swiftui,Swiftui,当视图模型嵌套在另一个视图模型中时,我不确定为什么视图没有得到更新。我的理解是,子视图模型中的@Published属性将触发父视图模型中的更改,从而将更改推送到UI 这是子视图模型: class FilterViewModel : ObservableObject, Identifiable { var id = UUID().uuidString var name = "" var backgroundColour = ""

当视图模型嵌套在另一个视图模型中时,我不确定为什么视图没有得到更新。我的理解是,子视图模型中的@Published属性将触发父视图模型中的更改,从而将更改推送到UI

这是子视图模型:

class FilterViewModel : ObservableObject, Identifiable {

    var id = UUID().uuidString
    var name  = ""
    var backgroundColour = ""
    @Published var selected = false

    private var cancellables = Set<AnyCancellable>()

    init(name: String){
        self.name = name
    
        $selected.map { _ in
            self.selected ? "Orange" : "LightGray"
        }
        .assign(to: \.backgroundColour, on: self)
        .store(in: &cancellables)
     }

    func changeSelected() {
    
        self.selected = !self.selected
    }
}
但是,我想尝试一系列过滤器视图模型:

class FilterListViewModel: ObservableObject {

    @Published var filtersVMS = [FilterViewModel]()

    init(){
        filtersVMS = [
            FilterViewModel(name: "A"),
            FilterViewModel(name: "B"),
            FilterViewModel(name: "C"),
            FilterViewModel(name: "D")
        ]
    }
}
但是,单击按钮时不会更新以下视图

struct ContentView: View {

    @ObservedObject var filterListVM = FilterListViewModel()

    Button(action: { filterListVM[0].changeSelected()}, label: {
        Text(filterListVM[0].name)
            .background(Color(filterListVM[0].backgroundColour))
    })
}

最简单的方法是将
filtervewmodel
定义为结构。因此,它是一种值类型。值更改时,结构也会更改。然后,ListViewModel会触发一个更改

struct FilterViewModel : Identifiable {

    var id = UUID().uuidString
    var name  = ""
    var backgroundColour = ""
    var selected = false

    private var cancellables = Set<AnyCancellable>()

    init(name: String){
        self.name = name
    
        $selected.map { _ in
            self.selected ? "Orange" : "LightGray"
        }
        .assign(to: \.backgroundColour, on: self)
        .store(in: &cancellables)
     }

    mutating func changeSelected() {
    
        self.selected = !self.selected
    }
}
struct FilterViewModel:可识别{
var id=UUID().uuistring
var name=“”
var backgroundcolor=“”
所选变量=false
private var cancelables=Set()
init(名称:String){
self.name=名称
$selected.map{uu}in
自选“橙色”:“浅灰色”
}
.分配(给:\.背景颜色,在:self上)
.store(在:&可取消项中)
}
mutating func changeSelected(){
self.selected=!self.selected
}
}

另一种解决方案是对子模型使用单独的视图:

struct FilterView: View {
    @ObservedObject var filterVM: FilterViewModel

    var body: some View {
      Button(action: { filterVM.changeSelected()}, label: {
        Text(filterVM.name)
            .background(Color(filterVM.backgroundColour))
      })
    }
}
所以在父视图中,现在我们可以将其用作

struct ContentView: View {

    @ObservedObject var filterListVM = FilterListViewModel()

    // ...

    FilterView(filterVM: filterListVM[0])
}

谢谢,这很有效。您知道为什么这样做比通过其父级引用子VM更有效吗?ObservedObject只观察到一个级别发布的值发生变化,在您的情况下,当内部子属性发生变化时,对子级的引用不会发生变化。
struct ContentView: View {

    @ObservedObject var filterListVM = FilterListViewModel()

    // ...

    FilterView(filterVM: filterListVM[0])
}