Il salvataggio dell'entità dati core in popover in SwiftUI genera zero errore senza passare di nuovo .environment a SubView


15

Giocare con SwiftUI e Core Data mi ha portato a un problema curioso. Quindi la situazione è la seguente:

Ho una vista principale "AppView" e una vista secondaria denominata "SubView". La vista SubView verrà aperta dalla vista AppView se faccio clic sul pulsante più in NavigationTitleBar come popover o foglio.

@Environment(\.managedObjectContext) var managedObjectContext
@State private var modal: Bool = false
...
Button(action: {
        self.modal.toggle()
      }) {
        Image(systemName: "plus")
      }.popover(isPresented: self.$modal){
        SubView()
      }

La vista SubView ha una piccola forma con due oggetti TextField per aggiungere un nome e un cognome. Gli input di questi due oggetti sono gestiti da due proprietà @State separate. Il terzo oggetto in questo modulo è un semplice pulsante, che dovrebbe salvare un nome e cognome in un'entità cliente collegata per 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")
}

Se provo a salvare l'entità cliente in questo modo, ottengo l'errore: "nilError", in particolare: "Errore non risolto Errore dominio = Foundation._GenericObjCError Code = 0" (null) ", [:]" da NSError.

Ma dopo aver capito, che quando aggiungo .environment(\.managedObjectContext, context)a SubView () lo chiamo così SubView().environment(\.managedObjectContext, context)funziona come un incantesimo.

Qualcuno sa, perché ho bisogno di passare una seconda volta a managedObjectContext? Ho pensato che ho solo bisogno di passare una volta il managedObjectContext per usarlo nella gerarchia dell'intera vista, come in 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)

È perché chiamando SubView () in questo modo, la vista non fa parte della gerarchia della vista? Non lo capisco


1
Ho osservato lo stesso comportamento su iOS 13.1. Xcode 11.1
Arun Patra,

Non sei il primo a trovare questo problema, l'ho risolto passando il contesto come parametro. Speriamo che Apple lo risolva presto.
Michael Salmon,

1
Come previsto, questo sembra essere un bug nel compilatore di Swift / SwiftUI. Quindi Harlan Haskins di Apple mi ha dato la conferma di ciò: bugs.swift.org/browse/SR-11607 - Quindi spero che questo problema verrà risolto presto. Per la soluzione rapida: il passaggio di .environment (\. ManagedObjectContext, contesto) al popover di SubView funziona.
lukas_nitaco,

Risposte:


24

WOW QUESTO DROVE ME NUTS! Soprattutto perché gli errori non ti dicono assolutamente nessuna informazione su come risolvere.

Ecco la correzione fino alla risoluzione del bug in Xcode:

        .navigationBarItems(trailing:
            Button(action: {
                self.add = true
            }, label: {
                Text("Add Todo List")
            }).sheet(isPresented: $add, content: {
                AddTodoListView().environment(\.managedObjectContext, managedObjectContext)
            })
        )

Basta aggiungere .environment(\.managedObjectContext, managedObjectContext)alla vista secondaria (un modale, in questo esempio).


8
un aiuto immenso per tutti noi abbastanza coraggiosi da svilupparci in SwiftUI proprio ora ...
Apostolos Apostolidis

Risolto anche il mio problema. Grazie.
P. Ent,

1
Il mio amico! Perché SwiftUI lo rende necessario? L'ambiente dovrebbe essere accessibile a livello globale.
pulse4life

Ma perché è necessario? Davvero strano che SwiftUI non lo faccia automaticamente ...
Loris Foe,

È necessario perché è l'unica soluzione al bug in questo momento. Apparentemente Apple sta lavorando a una soluzione. Ricorda che SwiftUI è ancora molto nuovo.
stardust4891,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.