在SwiftUI中将核心数据实体保存在弹出窗口中会抛出nilError,而不会再次将.environment传递给SubView


15

SwiftUI和Core Data的“玩法”使我陷入一个奇怪的问题。因此,情况如下:

我有一个主视图“ AppView”和一个名为“ SubView”的子视图。如果我单击NavigationTitleBar中的加号按钮(即弹出窗口或工作表),将从AppView视图中打开SubView视图。

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

SubView视图的形式有点小,带有两个TextField对象,用于添加一个姓氏和一个姓氏。这两个对象的输入由两个单独的@State属性处理。此表单中的第三个对象是简单按钮,该按钮应将前名和姓氏保存到附加的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")
}

如果我尝试以这种方式保存Customer实体,则会收到错误:“ nilError”,特别是:NSError中出现了“未解决的错误Error Domain = Foundation._GenericObjCError Code = 0“(null)”,[:]“。

但是在弄清楚之后,当我.environment(\.managedObjectContext, context)像这样将SubView().environment(\.managedObjectContext, context)其添加到SubView()时,它就像是一种魅力。

有谁知道,为什么我需要第二次传递managedObjectContext?我以为,我只需要传递一次ManagedObjectContext即可在整个视图层次结构中使用它,就像在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)

是否因为以这种方式调用SubView()而使视图不属于视图层次结构?我不明白...


1
我在iOS 13.1上观察到了相同的行为。Xcode 11.1
Arun Patra

您不是第一个发现此问题的人,我通过将上下文作为参数来解决了。希望苹果公司会尽快修复它。
迈克尔·萨蒙

1
不出所料,这似乎是Swift / SwiftUI编译器中的错误。因此,苹果公司的哈兰·哈斯金斯(Harlan Haskins)给予了我以下确认:bugs.swift.org/browse/SR-11607-所以我希望这一问题很快得到解决。快速修复方法:将.environment(\。managedObjectContext,context)传递到SubView弹出框即可。
lukas_nitaco

Answers:


24

哇,这让我发疯了!尤其是因为错误告诉您绝对没有有关如何修复的信息。

在解决Xcode中的错误之前,这里是解决方法:

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

只需添加.environment(\.managedObjectContext, managedObjectContext)到辅助视图(在此示例中为Modal)即可。


8
对我们所有人的巨大帮助,他们现在已经足够勇敢地在SwiftUI中进行开发……
Apostolos Apostolidis,

也解决了我的问题。谢谢。
P. Ent

1
天哪!为什么SwiftUI需要这样做?应该全局访问环境。
–puls4life

但是为什么有必要呢?SwiftUI不会自动使其变得非常奇怪……
Loris Foe

这是必要的,因为它是目前唯一的bug解决方案。苹果显然正在努力修复。请记住,SwiftUI仍然很新。
stardust4891
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.