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.
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 ForEach
in 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:))
removeSubItem
could 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()
}
}