Home > Software design >  Sending an NSManagedObjectID to a struct / view
Sending an NSManagedObjectID to a struct / view

Time:06-01

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.

  • Related