Temel veri varlıklarını SwiftUI'de popover'e kaydetmek, .environment öğesini tekrar SubView'a geçirmeden nilError değerini atar


15

SwiftUI ve Core Data ile oynamak beni meraklı bir soruna getirdi. Durum şu şekildedir:

Ana görünümü "AppView" ve "SubView" adlı bir alt görünümü var. NavigationTitleBar'daki artı düğmesini popover veya sayfa olarak tıklarsam SubView görünümü AppView görünümünden açılır.

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

SubView görünümünde bir ad ve soyadı eklemek için iki TextField nesnesi içeren küçük bir form vardır. Bu iki nesnenin girdileri iki ayrı @State özelliği tarafından işlenir. Bu formdaki üçüncü nesne, CoreData için ekli bir Müşteri Varlığına bir ön ve soyadı kaydetmesi gereken basit düğmedir.

...
@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")
}

Müşteri varlığını bu şekilde kaydetmeye çalışırsam, şu hatayı alıyorum: "nilError", özellikle: "Çözülemeyen hata Hata Domain = Foundation._GenericObjCError Code = 0" (null) ", [:]" NSError'dan.

Ama anladıktan sonra .environment(\.managedObjectContext, context), SubView () çağrısına eklediğimde SubView().environment(\.managedObjectContext, context)bir cazibe gibi çalışır.

Herkes bilen, neden manageObjectContext ikinci kez geçmek gerekir? SceneDelegate.swift gibi tüm görünüm hiyerarşisinde kullanmak için bir kez yönetilenObjectContext geçirmeniz gerektiğini düşündüm:

    // 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)

SubView () bu şekilde çağrıldığında görünüm görünüm hiyerarşisinin bir parçası değil mi? Anlamıyorum ...


1
İOS 13.1'de de aynı davranışı gözlemledim. Xcode 11.1
Arun Patra

Bu sorunu ilk bulan siz değilsiniz, bağlamı parametre olarak ileterek çözdüm. Umarım Apple yakında düzeltir.
Michael Salmon

1
Beklendiği gibi bu Swift / SwiftUI Derleyicisi'nde bir hata gibi görünüyor. Apple'dan Harlan Haskins bana bunun için onay verdi: bugs.swift.org/browse/SR-11607 - Umarım yakında bu sorun çözülür . Hızlı düzeltme için.
lukas_nitaco

Yanıtlar:


24

Vay be bu beni deli somun! Özellikle hatalar size nasıl düzeltileceği hakkında hiçbir bilgi vermediğinden.

İşte Xcode'daki hata çözülene kadar düzeltme:

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

.environment(\.managedObjectContext, managedObjectContext)İkincil görünümünüze ekleyin (bu örnekte bir Modal).


8
SwiftUI şimdi geliştirmek için yeterince cesur hepimiz için muazzam yardım ...
Apostolos Apostolidis

Sorunumu da çözdüm. Teşekkür ederim.
P. Ent

1
Benim dostum! SwiftUI bunu neden gerekli kılıyor? Çevreye küresel olarak erişilmelidir.
pulse4life

Ama neden gerekli? SwiftUI'nin otomatik olarak yapmadığını gerçekten garip ...
Loris Foe

Gerekli, çünkü şu anda hataya tek çözüm bu. Apple görünüşe göre bir düzeltme üzerinde çalışıyor. Unutmayın SwiftUI hala çok yeni.
stardust4891
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.