การบันทึกเอนทิตีข้อมูลหลักใน popover ใน SwiftUI จะพ่น nilError โดยไม่ต้องผ่าน. สิ่งแวดล้อมไปยัง SubView อีกครั้ง


15

Playin 'กับ SwiftUI และ Core Data ทำให้ฉันมีปัญหาแปลก ๆ ดังนั้นสถานการณ์ดังต่อไปนี้:

ฉันมีมุมมองหลัก "AppView" และมุมมองย่อยที่ชื่อว่า "SubView" มุมมอง SubView จะถูกเปิดจากมุมมอง AppView ถ้าฉันคลิกปุ่มบวกใน NavigationTitleBar ในฐานะ popover หรือชีต

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

ถ้าฉันพยายามบันทึกเอนทิตีของลูกค้าด้วยวิธีนี้ฉันจะได้รับข้อผิดพลาด: "nilError" โดยเฉพาะ: "ข้อผิดพลาดที่ยังไม่ได้แก้ไขข้อผิดพลาด Domain = Foundation._GenericObjCError Code = 0" (null) ", [:]" จาก NSError

แต่หลังจากที่คิดออกว่าเมื่อฉันเพิ่มลง.environment(\.managedObjectContext, context)ใน SubView () โทรเช่นนั้นSubView().environment(\.managedObjectContext, context)มันทำงานเหมือนมีเสน่ห์

ไม่มีใครรู้ว่าทำไมฉันต้องผ่านการจัดการ ObjectContext เป็นครั้งที่สอง? ฉันคิดว่าฉันต้องผ่านการจัดการ ObjectContext หนึ่งครั้งเพื่อใช้ในลำดับชั้นของมุมมองทั้งหมดเช่นเดียวกับใน 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
อรุณภัทรา

คุณไม่ใช่คนแรกที่พบปัญหานี้ฉันแก้ไขได้โดยส่งบริบทเป็นพารามิเตอร์ หวังว่า Apple จะซ่อมมันในไม่ช้า
Michael Salmon

1
ตามที่คาดไว้ดูเหมือนว่าจะเป็นข้อบกพร่องในคอมไพเลอร์ของ Swift / SwiftUI ดังนั้น Harlan Haskins จาก Apple ได้ให้การยืนยันกับฉัน: bugs.swift.org/browse/SR-11607 - ดังนั้นฉันหวังว่าจะได้รับการแก้ไขในไม่ช้า สำหรับการแก้ไขอย่างรวดเร็ว: การส่งผ่าน. สภาพแวดล้อม (\. managedObjectContext บริบท) ไปยัง SubView popover ทำงาน
lukas_nitaco

คำตอบ:


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. เอน

1
เพื่อนของฉัน! ทำไม SwiftUI ถึงทำสิ่งนี้จำเป็น? ควรเข้าถึงสิ่งแวดล้อมทั่วโลก
pulse4life

แต่ทำไมถึงจำเป็น? แปลกจริงๆที่ SwiftUI ไม่ได้ทำมันโดยอัตโนมัติ ...
Loris Foe

มันจำเป็นเพราะมันเป็นทางออกเดียวสำหรับข้อบกพร่องในขณะนี้ เห็นได้ชัดว่า Apple กำลังแก้ไขปัญหา โปรดจำไว้ว่า SwiftUI ยังใหม่มาก
stardust4891
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.