Guardar la entidad de datos centrales en popover en SwiftUI arroja nilError sin pasar .environment a SubView nuevamente


15

Jugar con SwiftUI y Core Data me llevó a un curioso problema. Entonces la situación es la siguiente:

Tengo una vista principal "AppView" y una vista secundaria llamada "SubView". La vista SubView se abrirá desde la vista AppView si hago clic en el botón más en NavigationTitleBar como popover u hoja.

@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 tiene una pequeña forma con dos objetos TextField para agregar un nombre y un apellido. Las entradas de estos dos objetos son manejadas por dos propiedades @State separadas. El tercer objeto en este formulario es un botón simple, que debe guardar el nombre y el apellido en una entidad de cliente adjunta para 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 trato de guardar la entidad del Cliente de esta manera, obtengo el error: "nilError", especialmente: "Error no resuelto Error Domain = Foundation._GenericObjCError Code = 0" (nulo) ", [:]" de NSError.

Pero después de descubrirlo, eso cuando agrego .environment(\.managedObjectContext, context)a la llamada SubView () así SubView().environment(\.managedObjectContext, context)funciona de maravilla .

¿Alguien sabe por qué necesito pasar el objeto de contexto gestionado por segunda vez? Pensé, que solo necesito pasar el contexto de objeto gestionado una vez para usarlo en toda la jerarquía de vistas, como en 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)

¿Es porque al llamar a SubView () de esta manera, la vista no es parte de la jerarquía de vistas? No lo entiendo ...


1
Observé el mismo comportamiento en iOS 13.1. Xcode 11.1
Arun Patra

No eres el primero en encontrar este problema, lo resolví pasando el contexto como un parámetro. Esperemos que Apple lo arregle pronto.
Michael Salmon

1
Como se esperaba, esto parece ser un error en el compilador de Swift / SwiftUI. Entonces, Harlan Haskins de Apple me dio la confirmación de eso: bugs.swift.org/browse/SR-11607 - Así que espero que esto se solucione pronto. Para la solución rápida: Pasar .environment (\. ManagedObjectContext, context) al popover SubView funciona.
lukas_nitaco

Respuestas:


24

¡GUAU ESTO ME DEJÓ TU NUTS! Especialmente porque los errores no le dicen absolutamente ninguna información sobre cómo solucionarlo.

Aquí está la solución hasta que se resuelva el error en Xcode:

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

Simplemente agregue .environment(\.managedObjectContext, managedObjectContext)a su vista secundaria (un Modal, en este ejemplo).


8
inmensa ayuda para todos nosotros lo suficientemente valientes como para desarrollarnos en SwiftUI en este momento ...
Apostolos Apostolidis

Resolvió mi problema también. Gracias.
P. Ent

1
¡Mi amigo! ¿Por qué SwiftUI hace esto necesario? Se debe acceder al medio ambiente a nivel mundial.
pulse4life

¿Pero por qué es necesario? Realmente extraño que SwiftUI no lo haga automáticamente ...
Loris Foe

Es necesario porque es la única solución al error en este momento. Apple aparentemente está trabajando en una solución. Recuerde que SwiftUI todavía es muy nuevo.
stardust4891
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.