Hello, I have the problem that I want to create a relationship between a list and its items. I have created relationships and also selected one-to-many for the list. But when I create multiple lists and add an item in the list, this item is added to each list and not only to the one. How can I set that the item is only added to the list that was selected?
Lists code
import SwiftUI
import CoreData
import Foundation
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: []) var items: FetchedResults<Item>
@State private var name: String = ""
var body: some View {
NavigationView {
VStack{
TextField("Text eingeben", text: $name)
.padding()
Button {
addItem()
} label: {
Text("Save")
}.padding()
List {
ForEach(items, id: \.self) { item in
NavigationLink(destination: ToDo()) {
Text(item.name ?? "Not found")
}
// Text(item.name ?? "Not found")
}
.onDelete(perform: deleteItems)
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Item(context: viewContext)
newItem.name = name
newItem.id = UUID()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { items[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
items list
import SwiftUI
import Foundation
import CoreData
struct ToDo: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: []) var todos: FetchedResults<ToDos>
@State private var todo: String = ""
var body: some View {
NavigationView {
VStack{
TextField("Text eingeben", text: $todo)
.padding()
Button {
addItem()
} label: {
Text("Save")
}.padding()
List {
ForEach(todos, id: \.self) { todos in
Text(todos.todo ?? "Not found")
}
.onDelete(perform: deleteItems)
}
}
}
}
private func addItem() {
withAnimation {
let newToDo = ToDos(context: viewContext)
newToDo.todo = todo
newToDo.id = UUID()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { todos[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
struct ToDo_Previews: PreviewProvider {
static var previews: some View {
ToDo()
}
}
Thank you!
There's no reference to the todos in the lists view. Both views just show all the lists and all of the todos. This is why regardless of what list is selected, all todos are displayed. What you need to do is pass the list object into the todos view and access the todos for the list from there and when adding a new todo to a list, you need to add it to do the respective list item.
I've implemented something like this before in my apps Aside and Deadlines, take a look at the source code for an example.