SwiftUI:创建CoreData对象后无法关闭工作表

时间:2020-09-26 19:41:33

标签: ios swift core-data swiftui

我正在尝试创建一个具有两个视图的非常基本的应用程序。主视图在NavigationView中显示CoreData对象,并具有工具栏按钮以打开“添加项目”模式表。 “添加项目”表应能够插入新的CoreData对象并关闭自身。我观察到的是,只要不插入模式表,只要它不插入CoreData对象,就可以将其关闭,但是一旦它与CoreData交互,我所有关闭该表的尝试都将不再起作用。另外,当工作表创建CoreData对象时,出现以下错误:

[演示]尝试本<< EM> TtGC7SwiftUI22SheetHostingControllerVS_7AnyView :0x7f8fcbc49a10>上<< EM> TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier _:0x7f8fcbd072c0>(来自<< EM> TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVVS_22_VariadicView_Children7ElementGVS_18StyleContextWriterVS_19SidebarStyleContext __:0x7f8fbbd0ba80> ),它已经呈现了<< em> TtGC7SwiftUI22SheetHostingControllerVS_7AnyView :0x7f8fcbd310b0>。

我使用的大多数代码是Xcode自己的样板代码,以及从网上借来的常见模式。你能帮我调试吗?

要重现,请在Xcode 12中使用CoreData创建一个新的SwiftUI iOS应用。将此内容替换为ContentView.swift:

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    
    @State var showingSheet: Bool = false

    var body: some View {
        NavigationView {
            List {
                //Text("static text")

                ForEach(items) { item in
                    Text("Item at \(item.timestamp!, formatter: itemFormatter)")
                }
                .onDelete(perform: deleteItems)
            }
            .navigationTitle("List of items")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button(action: {
                        showingSheet = true
                    }) {
                        Text("Open sheet")
                    }
                    .sheet(isPresented: $showingSheet) {
                        MySheetView(isPresented: $showingSheet)
                            .environment(\.managedObjectContext, viewContext)
                    }
                }
            }
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            offsets.map { items[$0] }.forEach(viewContext.delete)
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

private let itemFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .medium
    return formatter
}()

创建一个新的MySheetView.swift:

struct MySheetView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @Binding var isPresented: Bool
    
    var body: some View {
        NavigationView {
            Form {
                Button(action: {
                    self.isPresented = false
                }) {
                    Text("Dismiss this sheet")
                }
                
                Button(action: {
                    let newItem = Item(context: viewContext)
                    newItem.timestamp = Date()

                    do {
                        try viewContext.save()
                    } catch {
                        let nsError = error as NSError
                        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                    }
                }) {
                    Text("Add Item")
                }
            }
        }
    }
}

在运行时,如果您点击“打开工作表”,则可以点击“关闭此工作表”,它可以工作。但是,如果您点击“打开工作表”,然后点击“添加项目”,则会打印错误,并且“关闭此工作表”按钮将停止工作。 (您仍然可以向下滑动以消除工作表。)

我也尝试了presentationmode.wrappedvalue.dismiss()方法,但没有成功。

我发现,如果您在主视图上注释掉ForEach循环并取消注释Text(“静态文本”),那么在工作表上添加项目将不再输出错误或中断工作表的释放。因此,问题某种程度上与在主表上显示数据有关。但是显然我确实需要实际显示数据,并且这似乎是一个非常普通和基本的模式。我做错了吗?

1 个答案:

答案 0 :(得分:2)

您的from tkinter import * from tkcalendar import * from array import * root = Tk() i = 0 def getDateA(): a = array('b',[]*10000) global i f = i + 1 c = int(dataC.get()) b = int(dataB.get()) g = dataA.get() a.append(g[f]) d = int(a[b]) + int(a[c]) prompt.configure(text = d) dataA = Entry(root, text="Enter a", width = 20) dataA.grid(column = 2) dataB = Entry(root, text="Enter b", width = 20) dataB.grid(column = 3) dataC = Entry(root, text="Enter c", width = 20) dataC.grid(column = 4) my_button = Button(root, text="get date", command=getDateA) my_button.grid(column = 2) prompt = Label(root, text="Ingenting") prompt.grid(column=1) root.mainloop() 被放置在ToolbarItem上。只需在.sheet上进行更改即可。

这是ContentView的正文

NavigationView