macos - 为什么这个绑定在 macOS 的子视图中不起作用?
问题描述
我有几层 ObservableObjects 和 Published 属性。当我直接在视图中使用它们时,它们似乎按预期工作。但是,当我尝试将列表移动到它自己的类型时,父视图中的绑定似乎不起作用。
例如,为什么启用 ModelList,当您选择行时,Button 不会在启用和禁用之间切换。但是,如果您将其注释掉并启用 List.init 行,那么在选择和取消选择行时,按钮会正确启用和禁用。
这有效
View
List(selection: viewModel.dataStore.selection)
这不
View
ModelList(dataStore: viewModel.dataStore)
List(selection: dataStore.selection)
完整代码示例
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
// Using the the dataStore, the button bind works
// List.init(viewModel.dataStore.models, id: \.id, selection: $viewModel.dataStore.selection) {
// Text("Name: \($0.name)")
// }
// Using the dataStore in the subview, the button binding doesn't work
ModelList(dataStore: viewModel.dataStore)
Button(action: {
print("Delete")
}, label: {
Image(systemName: "minus")
})
.disabled($viewModel.dataStore.selection.wrappedValue.count == 0)
Text("Selection \($viewModel.dataStore.selection.wrappedValue.count)")
}
}
}
struct ModelList: View {
@ObservedObject public var dataStore: DataStore
var body: some View {
List.init(dataStore.models, id: \.id, selection: $dataStore.selection) {
Text("Name: \($0.name)")
}
}
}
class ViewModel: ObservableObject {
@Published var dataStore: DataStore = DataStore()
}
class DataStore: ObservableObject {
@Published public var selection = Set<Int>()
@Published public var models = [Model(id: 1, name: "First")]
}
struct Model: Identifiable {
let id: Int
let name: String
}
@main
struct LayersApp: App {
var body: some Scene {
WindowGroup {
ContentView(viewModel: ViewModel())
}
}
}
解决方案
子视图应该接受一个绑定,而不是另一个 ObservedObject。
@ObservedObject public var dataStore: DataStore
应该@Binding public var dataStore: DataStore
现在在使用子视图时,传入绑定ModelList(dataStore: $viewModel.dataStore)
完整的工作示例:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
ModelList(dataStore: $viewModel.dataStore)
Button(action: {
print("Delete \(viewModel.dataStore.selection)")
}, label: {
Image(systemName: "minus")
})
.disabled($viewModel.dataStore.selection.wrappedValue.count == 0)
Text("Selection \($viewModel.dataStore.selection.wrappedValue.count)")
}
}
}
struct ModelList: View {
@Binding public var dataStore: DataStore
var body: some View {
List.init(dataStore.models,
id: \.id,
selection: $dataStore.selection) {
Text("Name: \($0.name)")
}
}
}
class ViewModel: ObservableObject {
@Published var dataStore: DataStore = DataStore()
init() {
print("ViewModel")
}
}
class DataStore: ObservableObject {
@Published public var selection = Set<Int>()
@Published public var models = [Model(id: 1, name: "First")]
init() {
print("DataStore")
}
}
struct Model: Identifiable, Equatable {
let id: Int
let name: String
}
@main
struct LayersApp: App {
var body: some Scene {
WindowGroup {
ContentView(viewModel: ViewModel())
}
}
}
推荐阅读
- php - 无法设置客户端连接字符集:Codeigniter 中的 utf8
- node.js - 调度软件与客户端的交互
- mysql - 无法在我的查询请求中显示额外的属性
- python - 从字典创建多个 DataFrame
- bash - 如何将多个变量分配给固定大小的“表”输出
- c++ - 如何消除 Qt 折线图中顶点处的弧线?
- django - 如何在 django-oscar 结帐中将用户重定向到正确的页面?
- racket - 如何在球拍的正方形内找到一个点?
- vue.js - 如何在哈巴狗中使用 moment.js?属性或方法“时刻”未在实例上定义,但在渲染期间被引用
- hugo - 如何检测我正在运行 hugo 的内置服务器?