带有 CustomView 的 onTapGesture 不刷新子视图

onTapGesture with CustomView not Refreshing child view

我在使用自定义视图处理“onTapGesture”修饰符时遇到了一些问题。

struct CheckView: View {
    @State var isChecked: Bool = false
    
    var title: String
    var unitPrice: String
    
    var body: some View {
       Button(action: toggle){
           HStack{
               Image(systemName: isChecked ? "checkmark.square": "square")
               HStack {
                   Text(title)
                   Spacer()
                   Text("- $\(unitPrice)")
                       .frame(width: 65, alignment: .leading)
               }
               .foregroundColor(.black)
               Spacer()
           }
       }
    }
    
    func toggle() {
        isChecked = !isChecked
    }

上面的自定义视图是复选框行视图。当您单击该行时,它基本上只是将 sf 符号从选中框切换为空框。

在我创建它的父视图中,我从 Realm DB 中提取以填充列表视图中的项目。

@ObservedResults(Item.self) var items
    
@StateObject private var viewModel = ViewModel()

List {
    ForEach(items) { item in
        CheckView(title: item.itemDescription, unitPrice: String(format: "%.2f", item.unitPrice))
            .onTapGesture {
                viewModel.updateSelectedItems(item: item)
            }
    }
}

//ViewModel Function
@Published var selectedItems: [Item] = []
        
func updateSelectedItems(item: Item) {
    if (selectedItems.contains(item)) {
        selectedItems.removeAll(where: { [=11=] == item })
    }
    else {
        selectedItems.append(item)
    }
}

我想做的是使用点击手势调用视图模型中的函数,这样我就可以得到一个 运行 列表,其中包含已点击的项目。我可以确认 ViewModel 代码正常工作(我有一个调试警报,显示 Published 数组正在更新)但是发生的事情是 CheckView 没有刷新,就像在点击一行时,复选框 sf-symbol没有按应有的方式切换。好像什么都没做。

我怀疑这是 CheckView 上的 Button 和父视图上的 onTapGesture 之间的某种冲突,但我不确定。

如果您有任何想法,我们将不胜感激。

提前致谢。

您可以尝试以下方法将 ItemViewModel 传递给 CheckView

 struct CheckView: View {
     @EnvironmentObject var viewModel: ViewModel
     
    @State var item: Item
    @State var isChecked: Bool = false
    
    var body: some View {
        Button(action: {
            viewModel.updateSelectedItems(item: item)
            isChecked.toggle()
        }){
            HStack{
                Image(systemName: isChecked ? "checkmark.square": "square")
                HStack {
                    Text(item.itemDescription)
                    Spacer()
                    Text("- $\(String(format: "%.2f", item.unitPrice))")
                        .frame(width: 65, alignment: .leading)
                }
                .foregroundColor(.black)
                Spacer()
            }
        }
        .onAppear {
            isChecked = viewModel.selectedItems.contains(where: {[=10=].id == item.id})
        }
    }
}

并像这样使用它,没有 onTapGesture :

List {
    ForEach(items) { item in
        CheckView(item: item)
    }
}.environmentObject(viewModel)  // <-- here
    

根据上面的回答,如果你将 viewModel 传递给 CheckView,你能不能只检查该项目是否在 selectedItems 数组中?

struct CheckView: View {
  @EnvironmentObject var viewModel: ViewModel
 
  @State var item: Item
  var isSelected: Bool {
    viewModel.selectedItems.containts(item)
  }

  var body: some View {
    Button(action: {
      viewModel.updateSelectedItems(item: item)
    }) {
      HStack {
        Image(systemName: isSelected ? "checkmark.square": "square")
          HStack {
            Text(item.itemDescription)
            Spacer()
            Text("- $\(String(format: "%.2f", item.unitPrice))")
              .frame(width: 65, alignment: .leading)
            }
            .foregroundColor(.black)
            Spacer()
          }
        }
      }
  }