Zapisywanie podstawowej jednostki danych w oknie popover w SwiftUI powoduje wygenerowanie błędu nilError bez ponownego przekazania środowiska .View do SubView


15

Gra ze SwiftUI i Core Data przyniosła mi ciekawy problem. Tak więc sytuacja wygląda następująco:

Mam widok główny „AppView” i widok podrzędny o nazwie „SubView”. Widok SubView zostanie otwarty z widoku AppView, jeśli kliknę przycisk plus w NavigationTitleBar jako popover lub arkusz.

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

Widok SubView ma małą formę z dwoma obiektami TextField do dodania imienia i nazwiska. Dane wejściowe tych dwóch obiektów są obsługiwane przez dwie oddzielne właściwości @State. Trzecim obiektem w tym formularzu jest prosty przycisk, który powinien zapisać imię i nazwisko w załączonym podmiocie klienta dla 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")
}

Jeśli spróbuję zapisać encję Klienta w ten sposób, otrzymuję błąd: „nilError”, a zwłaszcza: „Nierozwiązany błąd Błąd Domena = Foundation._GenericObjCError Kod = 0” (null) ”, [:]” z NSError.

Ale po zorientowaniu się, że kiedy dodam .environment(\.managedObjectContext, context)do wywołania SubView () tak, SubView().environment(\.managedObjectContext, context)to działa jak urok.

Czy ktoś wie, dlaczego muszę przekazać parametr manageObjectContext po raz drugi? Pomyślałem, że muszę tylko raz przekazać manageObjectContext, aby użyć go w całej hierarchii widoków, jak w 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)

Czy to dlatego, że wywoływanie SubView () w ten sposób, widok nie jest częścią hierarchii widoków? Nie rozumiem tego ...


1
Obserwowałem to samo zachowanie na iOS 13.1. Xcode 11.1
Arun Patra

Nie jesteś pierwszym, który znalazł ten problem, rozwiązałem go, przekazując kontekst jako parametr. Mam nadzieję, że Apple naprawi to wkrótce.
Michael Salmon

1
Zgodnie z oczekiwaniami wydaje się, że jest to błąd w kompilatorze Swift / SwiftUI. Harlan Haskins z Apple dał mi na to potwierdzenie: bugs.swift.org/browse/SR-11607 - Mam więc nadzieję, że zostanie to wkrótce naprawione. Dla szybkiej poprawki: Przekazywanie środowiska. (\. ManagedObjectContext, kontekst) do popover działa SubView.
lukas_nitaco

Odpowiedzi:


24

WOW THRO DROVE ME NUTS! Zwłaszcza, że ​​błędy nie mówią absolutnie żadnych informacji, jak to naprawić.

Oto poprawka, dopóki błąd w Xcode nie zostanie rozwiązany:

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

Po prostu dodaj .environment(\.managedObjectContext, managedObjectContext)do drugiego widoku (w tym przykładzie modalny).


8
ogromna pomoc dla nas wszystkich na tyle odważnych, aby rozwijać się teraz w SwiftUI ...
Apostolos Apostolidis

Rozwiązałem również mój problem. Dziękuję Ci.
P. Ent

1
Mój koleś! Dlaczego SwiftUI sprawia, że ​​jest to konieczne? Dostęp do środowiska powinien być globalny.
pulse4life

Ale dlaczego jest to konieczne? Naprawdę dziwne, że SwiftUI nie robi tego automatycznie ...
Loris Foe

Jest to konieczne, ponieważ obecnie jest to jedyne rozwiązanie tego błędu. Apple najwyraźniej pracuje nad poprawką. Pamiętaj, że SwiftUI jest wciąż bardzo nowy.
stardust4891
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.