繁体   English   中英

为什么此绑定在 macOS 上的子视图中不起作用?

[英]Why doesn't this binding work when it's in a subview on macOS?

我有几层 ObservableObjects 和 Published 属性。 当我直接在视图中使用它们时,它们似乎按预期工作。 但是,当我尝试将列表移动到它自己的类型时,父视图中的绑定似乎不起作用。

例如,为什么启用了 ModelList,当您选择行时,Button 不会在启用和禁用之间切换。 但是,如果您将其注释掉并启用 List.init 行,则在选择和取消选择行时,按钮会正确启用和禁用。

https://youtu.be/7Kvh2w8z__4

这有效

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

子视图应该接受一个 Binding,而不是另一个 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())
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM