Việc lưu thực thể dữ liệu cốt lõi trong popover trong SwiftUI sẽ ném nilError mà không chuyển .envir sang SubView lần nữa


15

Chơi với SwiftUI và Core Data khiến tôi gặp vấn đề tò mò. Vì vậy, tình hình là như sau:

Tôi có chế độ xem chính "AppView" và chế độ xem phụ có tên "SubView". Chế độ xem SubView sẽ được mở từ chế độ xem AppView nếu tôi nhấp vào nút dấu cộng trong NavigationTitleBar dưới dạng popover hoặc sheet.

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

Khung nhìn SubView có một hình thức nhỏ với hai đối tượng TextField để thêm tên và họ. Đầu vào của hai đối tượng này được xử lý bởi hai thuộc tính @State riêng biệt. Đối tượng thứ ba trong biểu mẫu này là nút đơn giản, sẽ lưu tên trước và họ vào Thực thể khách hàng đính kèm cho 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")
}

Nếu tôi cố gắng lưu thực thể Khách hàng theo cách này, tôi sẽ gặp lỗi: "nilError", đặc biệt: "Lỗi chưa được giải quyết Tên miền = Foundation._GenericObjCError Code = 0" (null) ", [:]" từ NSError.

Nhưng sau khi nhận ra, khi tôi thêm .environment(\.managedObjectContext, context)vào lệnh gọi SubView () SubView().environment(\.managedObjectContext, context)thì nó hoạt động như một bùa mê.

Có ai biết, tại sao tôi cần phải vượt qua ManagedObjectContext lần thứ hai không? Tôi nghĩ rằng tôi chỉ cần vượt qua ManagedObjectContext một lần để sử dụng nó trong toàn bộ hệ thống phân cấp chế độ xem, như trong 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)

Có phải vì gọi SubView () theo cách này, chế độ xem không phải là một phần của hệ thống phân cấp chế độ xem? Tôi không hiểu điều đó ...


1
Tôi đã quan sát hành vi tương tự trên iOS 13.1. Xcode 11.1
Arun Patra

Bạn không phải là người đầu tiên tìm thấy vấn đề này, tôi đã giải quyết nó bằng cách chuyển ngữ cảnh dưới dạng tham số. Hy vọng Apple sẽ khắc phục sớm.
Michael Salmon

1
Như dự đoán, đây có vẻ là một lỗi trong Trình biên dịch của Swift / SwiftUI. Vì vậy, Harlan Haskins từ Apple đã cho tôi xác nhận rằng: bug.swift.org/browse/SR-11607 - Vì vậy, tôi hy vọng điều này sẽ sớm được khắc phục. Để khắc phục nhanh: Truyền .en môi trường (\. ManagedObjectContext, bối cảnh) cho các hoạt động popover SubView.
lukas_nitaco

Câu trả lời:


24

WOW NÀY RÚT RA TÔI! Đặc biệt là vì các lỗi cho bạn hoàn toàn không có thông tin nào về cách khắc phục.

Đây là cách khắc phục cho đến khi lỗi trong Xcode được giải quyết:

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

Chỉ cần thêm .environment(\.managedObjectContext, managedObjectContext)vào chế độ xem phụ của bạn (một Modal, trong ví dụ này).


8
giúp đỡ rất nhiều cho tất cả chúng ta đủ can đảm để phát triển trong SwiftUI ngay bây giờ ...
Apostolos Apostolidis

Giải quyết vấn đề của tôi là tốt. Cảm ơn bạn.
P. Ent

1
Anh bạn của tôi! Tại sao SwiftUI làm điều này cần thiết? Môi trường nên được truy cập trên toàn cầu.
Pulse4life

Nhưng tại sao nó lại cần thiết? Thật kỳ lạ khi SwiftUI không tự động làm điều đó ...
Loris Foe

Điều này là cần thiết bởi vì nó là giải pháp duy nhất cho lỗi ngay bây giờ. Apple rõ ràng đang làm việc trên một bản sửa lỗi. Hãy nhớ SwiftUI vẫn còn rất mới.
stardust4891
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.