I'm complete new to swift, swiftui and coredata. I have good programming experience in other languages, but swift is its own world. :-)
Important information: it's for macOS not iOS!!
My problem: I want to edit a Dataset in an separate view displayed in a sheet. I followed this example (SwiftUI update view on core data object change), but when trying to run, my NSManagedObjectID is allway nil.
The ContentView (shortened)
import SwiftUI
import CoreData
struct ContentView: View {
@State public var selectedBookId: NSManagedObjectID?
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Books.title, ascending: true)],
animation: .default)
private var books: FetchedResults<Books>
@State private var showingEditScreen = false
var body: some View {
NavigationView {
List {
ForEach(books, id: \.self) { book in
HStack {
NavigationLink {
HStack {
Button {
// here store objectID to var
selectedBookId = book.objectID
showingEditScreen.toggle()
} label: {
Label("", systemImage: "pencil")
}
}
.padding(10.0)
} label: {
Text(book.title!)
}
}
}.onDelete(perform: deleteBooks)
}
.toolbar {
ToolbarItem(placement: .automatic) {
// here goes blabla
}
}
Text("Bitte zuerst ein Buch auswählen!")
}
.sheet(isPresented: $showingEditScreen) {
// Run EditBookView an send bookId
EditBookView(bookId: selectedBookId).environment(\.managedObjectContext, self.viewContext)
}
}
}
My EditView looks like this
import SwiftUI
struct EditBookView: View {
@Environment(\.managedObjectContext) var moc
@Environment(\.dismiss) var dismiss
var bookId: NSManagedObjectID! // This is allways nil!!
var book: Books {
moc.object(with: bookId) as! Books
}
@State private var title = ""
@State private var review = ""
var body: some View {
Form {
Text("Edit Book").font(.title)
Spacer()
Section {
TextField("Buchname", text: $title)
TextEditor(text: $review)
} header: {
Text("Schreibe eine Zusammenfassung")
}
Spacer()
Section {
HStack {
Button("Save") {
// add the book
// here code for update
try? moc.save()
dismiss()
}
Button("Cancel") {
print(bookId) // shows "nil"
dismiss()
}
}
}
Spacer()
}
.onAppear {
self.title = self.book.title ?? ""
self.review = self.book.review ?? ""
}
.padding(10.0)
}
}
CodePudding user response:
First: thanks for all the good hints. In the end, I could solve the problem using
@ObservedObject var aBook: Books
at the beginning of my EditView.
The button itself has the following code
Button {
showingEditScreen.toggle()
} label: {
Label("", systemImage: "pencil")
}.sheet(isPresented: $showingEditScreen) {
EditBookView(aBook: book).environment(\.managedObjectContext, self.viewContext)
}
This way, I can send the whole book object of a single book item to the edit view and I can use it.