Search code examples
swiftcore-dataswiftuinsfetchrequestnsobject

Swift Core-Data delete items from attribute list


I am working on a core data project. Currently I have one Entity (Item) with the following attributes:

@NSManaged public var title: String?
@NSManaged public var list: [String]

I am displaying the Entitys in a list using a List with ForEach. With a navigation link I open up another view if the user selects one Item.

Main List Code:

struct ItemList: View {
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \Item.title, ascending: true)]) 
var ItemFetch: FetchedResults<Item>

   var body: some View {
      NavigationView {
         List {
            ForEach(ItemFetch, id: \.self {item in
               NavigationLink(destination: ItemView(Item: item) {
                  Text(item.title)
               }
            }
            .onDelete(perform: removeItem(at:))
         }
      }
   }
   private func removeItem(at offsets: IndexSet) {
           for index in offsets {
               let item = ItemFetch[index]
               viewContext.delete(item)
        }
    }
}

Second View Code:

struct ItemView: View {

@Environment(\.managedObjectContext) var viewContext
@ObservedObject var Item: Item

var body: some View{
NavigationView {
   List {
      ForEach { Item.list.indices { entry in
         Text(self.Item.list[entry]
      }
   }
   .navigationBarItem(
          trailing:
               Button(action: {
                   self.Item.list.append("SubItem")
       }) {
                   Text("Add SubItem")
        })
      }
   }
}

The user can add a SubItem to the list by pressing a button.

Also can the Items in the Item List be removed by swiping.

Now I want that the user can remove SubItems in the SubItems List by swiping as well. If I try to implement the same func then the user will remove a Item by deleting a SubItem which is not what I want.

I don't know how to use the FetchRequest to only fetch the attribute called list. Is there a way to do this or another way to delete the SubItems?

Thanks.


Solution

  • The code posted in the question isn't actually working.

    If you want to be able to run queries on the subitems, you will probably want to create a new entity for them and link both entities using a Core Data 1-to-n relationship.

    If you want to stick to an array of Strings to store the subitems however, you can achieve the swipe to delete functionality by adding:

    .onDelete(perform: removeSubItem(at:))

    to the ForEachin ItemView, i.e.

    ForEach(Item.list, id: \.self) { entry in // you should actually call it "item" to avoid confusion...
        Text(entry)
    }.onDelete(perform: removeSubItem(at:))
    

    removeSubItemcould look like this:

    private func removeSubItem(at offsets: IndexSet) {
        for index in offsets {
            Item.list.remove(at: index)  // you should actually call it "item" to avoid confusion...
            try? viewContext.save()
        }
    }