Jouer avec SwiftUI et Core Data m'a posé un curieux problème. La situation est donc la suivante:
J'ai une vue principale "AppView" et une vue secondaire nommée "SubView". La vue SubView sera ouverte à partir de la vue AppView si je clique sur le bouton plus dans le NavigationTitleBar en tant que popover ou feuille.
@Environment(\.managedObjectContext) var managedObjectContext
@State private var modal: Bool = false
...
Button(action: {
self.modal.toggle()
}) {
Image(systemName: "plus")
}.popover(isPresented: self.$modal){
SubView()
}
La vue SubView a une petite forme avec deux objets TextField pour ajouter un prénom et un nom de famille. Les entrées de ces deux objets sont gérées par deux propriétés @State distinctes. Le troisième objet de ce formulaire est un simple bouton, qui devrait enregistrer le prénom et le nom de famille dans une entité client attachée pour CoreData.
...
@Environment(\.managedObjectContext) var managedObjectContext
...
Button(action: {
let customerItem = Customer(context: self.managedObjectContext)
customerItem.foreName = self.forename
customerItem.surname = self.surname
do {
try self.managedObjectContext.save()
} catch {
print(error)
}
}) {
Text("Speichern")
}
Si j'essaie d'enregistrer l'entité Client de cette façon, j'obtiens l'erreur: "nilError", spécialement: "Erreur non résolue Error Domain = Foundation._GenericObjCError Code = 0" (null) ", [:]" de NSError.
Mais après avoir compris, que lorsque j'ajoute .environment(\.managedObjectContext, context)
à l'appel SubView (), SubView().environment(\.managedObjectContext, context)
cela fonctionne comme un charme.
Est-ce que quelqu'un sait pourquoi je dois passer le managedObjectContext une deuxième fois? Je pensais que j'avais juste besoin de passer le managedObjectContext une fois pour l'utiliser dans toute la hiérarchie des vues, comme dans SceneDelegate.swift:
// Get the managed object context from the shared persistent container.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
// Add `@Environment(\.managedObjectContext)` in the views that will need the context.
let contentView = AppView().environment(\.managedObjectContext, context)
Est-ce parce que l'appel de SubView () de cette façon, la vue ne fait pas partie de la hiérarchie des vues? Je ne comprends pas ...