.ondelete 带有部分的 SwiftUI 列表

Posted

技术标签:

【中文标题】.ondelete 带有部分的 SwiftUI 列表【英文标题】:.ondelete SwiftUI List with Sections 【发布时间】:2020-10-19 12:30:27 【问题描述】:

我无法在 SwiftUI 列表中发布删除和移动行的方法。

我有类别的模型:

struct Category: Identifiable 

    var id = UUID()
    var title: String
    var number: Int
    var items: [ChecklistItem]

    func deleteListItem(whichElement: IndexSet) 
      items.remove(atOffsets: whichElement)
    

    func moveListItem(whichElement: IndexSet, destination: Int) 
      items.move(fromOffsets: whichElement, toOffset: destination)
    



清单项目:

struct ChecklistItem: Identifiable 
  
  let id = UUID()
  var name: String
  var isChecked = false
    

和清单:

class Checklist: ObservableObject 

  @Published var items = [Category]()

这是我的列表视图:

struct ChecklistView: View 

  @EnvironmentObject var checklist: Checklist
  @State var newChecklistItemViewIsVisible = false

  var body: some View 
    NavigationView 
      List 
        ForEach(checklist.items)  category in
            Section(header: Text(category.title)) 
                ForEach(category.items)  item in
                    HStack 
                      Text(item.name)
                      Spacer()
                      Text(item.isChecked ? "✅" : "????")
                    
                    .background(Color.white)
                    .onTapGesture 
                        if let matchingIndex =
                            checklist.items[category.number].items.firstIndex(where:  $0.id == item.id ) 
                            checklist.items[category.number].items[matchingIndex].isChecked.toggle()
                      
                    
                
                .onDelete(perform: checklist.items[category.number].deleteListItem)
                .onMove(perform: checklist.items[category.number].moveListItem)
            
        
      
      .navigationBarItems(
        leading: Button(action: 
            self.newChecklistItemViewIsVisible = true

        ) 
          HStack 
            Image(systemName: "plus.circle.fill")
            Text("Add")
          
        ,
        trailing: EditButton()
      )
      .navigationBarTitle("List")
    
    .onAppear 
        //print("ContentView appeared!")
    
    .sheet(isPresented: $newChecklistItemViewIsVisible) 
      NewChecklistItemView(checklist: self.checklist)
    
  


struct ContentView_Previews: PreviewProvider 
  static var previews: some View 
      ChecklistView()

  

我不能使用 .ondelete 和 .onmove 方法,因为我不能在 struct 中使用变异方法。如何更改我的代码以添加功能以删除和移动 List with Sections 中的项目?

【问题讨论】:

【参考方案1】:

您需要为您的函数使用mutating 修饰符,并更新代码

struct Category: Identifiable 

    // ... other code

    mutating func deleteListItem(_ whichElement: IndexSet) 
      items.remove(atOffsets: whichElement)
    

    mutating func moveListItem(_ whichElement: IndexSet, _ destination: Int) 
      items.move(fromOffsets: whichElement, toOffset: destination)
    

和类似的用法

.onDelete  indexSet in 
   checklist.items[category.number].deleteListItem(indexSet) 

.onMove  indexSet, dest in 
   checklist.items[category.number].moveListItem(indexSet, dest) 

【讨论】:

使用 Xcode 12 测试。我没有更改其他代码。它可能是你改编时出现的东西。 我也使用 Xcode 12,只是将 .onDelete(perform: checklist.items[category.number].deleteListItem) 和 .onMove(perform: checklist.items[category.number].moveListItem) 更改为你的。但无论如何都会得到这个错误。 如果我使用我的方法,我会收到错误不允许部分应用“变异”方法 提供的代码快照的两个部分都是有意义的——你必须同时调整它们。首先允许变异类别,其次修复 Partial ... 错误。

以上是关于.ondelete 带有部分的 SwiftUI 列表的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI,列表行添加按钮

SwiftUI:有条件的 onDelete

如何使用 .reversed() 处理 SwiftUI 列表数组的 .onDelete

SwiftUI .onDelete 抛出致命错误:索引超出范围

SwiftUI .onDelete 从 ForEach 获取 var

SwiftUI List .onDelete:索引超出范围