从SwiftUI上的分区列表中删除项目



概述

我用核心数据做一个简单的应用程序我有两个实体用户和地区,该应用程序按地区显示用户列表。问题是在删除操作中,列表从第一部分删除用户。如果我试图从第二部分删除第二个用户,它会从第一部分中删除第二用户。

我认为索引集在发送节的索引时出错了,但当我试图将onDelete更改为嵌套的forEach时,不起作用

这是代码

import SwiftUI
struct ContentView: View {
    @Environment(.managedObjectContext) var moc
    @FetchRequest(entity: User.entity(), sortDescriptors: [NSSortDescriptor(keyPath: User.name, ascending: true)]) var users: FetchedResults<User>
    @FetchRequest(entity: Territory.entity(), sortDescriptors: [NSSortDescriptor(keyPath: Territory.name, ascending: true)]) var territories: FetchedResults<Territory>
    @State private var showAddUser = false

       var body: some View {
           GeometryReader{ geometry in
               NavigationView {
                   ZStack {
                       List {
                           ForEach(self.territories, id: .self) { territorie in
                            Section(header: Text(territorie.wrappedName)) {
                                ForEach(territorie.usersArray, id: .self) { user in
                                    NavigationLink(destination: UserView(user: user)) {
                                        VStack{
                                            HStack{
                                               Text("user")
                                                Spacer()
                                                Text(user.dayLastVisit)
                                                    .padding(.horizontal)
                                            }
                                            HStack {
                                                Text(user.wrappedEmoji)
                                                    .font(.largeTitle)
                                                VStack(alignment: .leading) {
                                                    Text("(user.wrappedName + " " + user.wrappedLastName)")
                                                        .font(.headline)
                                                    Text(user.wrappedType)
                                                }
                                                Spacer()
                                            }
                                        }
                                    }
                                }.onDelete(perform: self.deleteItem)
                            }
                           }

                       }
                       .listStyle(GroupedListStyle())
                       .environment(.horizontalSizeClass, .regular)
                       VStack {
                           Button(action:{ self.showAddRUser.toggle()}){
                               ButtonPlus(icon:"plus")}
                           .offset(x: (geometry.size.width * 0.40), y: (geometry.size.height  * 0.38))
                           .sheet(isPresented: self.$showAddUser){
                               NewUserView().environment(.managedObjectContext, self.moc)
                                  }
                       }
                   }
               .navigationBarTitle("Users")
                   .navigationBarItems( trailing: HStack {
                    EditButton()
                    Button(action:{self.showAddUser.toggle()}){
                    ButtonNew(text:"Nueva")}
                    }
                    .sheet(isPresented: self.$showAddUser){
                        NewUserView().environment(.managedObjectContext, self.moc)
                   }
                   )
               }
           }
       }
    func deleteItem(at offsets: IndexSet) {
        for offset in offsets { 
            let user = users[offset]
            //borarlo del context
            moc.delete(user)
        }
        try? moc.save()
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我学得很快,所以我会感谢的任何帮助

您需要传入节索引和行索引,以便知道要删除哪个嵌套项。像这样的东西。

.onDelete { self.deleteItem(at: $0, in: sectionIndex) }

并更改您的函数以接受该部分索引:

func deleteItem(at offsets: IndexSet, in: Int)

在您的情况下,您可能会传入类似territorie.id的内容作为节索引,并使用它来删除正确的项。或者将territorie对象传递给正确的用户。只有索引不会让你到达那里。希望这一切都有意义!

对我来说,解决方案如下:

ForEach(self.territories, id: .self) { territorie in
    Section(header: Text(territorie.wrappedName)) {
        ForEach(territorie.usersArray, id: .self) { user in
            // your code here
        }
        .onDelete { indexSet in
            for index in indexSet {
                moc.delete(territorie[user])
            }
                
            // update the view context
            moc.save()
        }
    }
}

indexSet中的index返回该特定节中应删除的项。因此,如果我删除节的第一项,它将返回0。

territorie返回该部分中包含的所有项目的列表。因此,使用territorie[index]将返回要删除的特定用户对象。

现在我们有了要删除的对象,我们可以将其传递给moc.delete(territorie[index])。最后,我们用moc.save()保存它。

旁注:虽然Misael使用了变量"territorie",但我更喜欢使用变量名section

感谢Kevin Renskers的帮助,他找到了解决方案。我只是在函数中添加一个.onDelete { self.deleteItem(at: $0, in: territorie)},然后使用该区域中的相同arrayUsers。

 func deleteItem(at offsets: IndexSet, in ter: Territory) {
        
        for offset in offsets {
             let user =  ter.usersArray[offset] 
            moc.delete(user)
            
        }
        try? moc.save()
    }

最新更新