SwiftUI:创建CoreData对象后无法关闭工作表 [英] SwiftUI: Cannot dismiss sheet after creating CoreData object

查看:31
本文介绍了SwiftUI:创建CoreData对象后无法关闭工作表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a very basic app with two views. The main view displays CoreData objects in a NavigationView and has a toolbar button to open an "add item" modal sheet. The "add item" sheet should be able to insert a new CoreData object and dismiss itself. What I am observing is that the modal sheet can be dismissed as long as it doesn't insert a CoreData object, but once it does interact with CoreData, all my attempts to dismiss the sheet no longer work. Also, when the sheet creates a CoreData object, I get the following error:

[演示文稿]尝试呈现< TtGC7SwiftUI22SheetHostingControllerVS_7AnyView :0x7f8fcbc49a10>在< TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier _上:0x7f8fcbd072c0>(从< TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVVS_22_VariadicView_Children7ElementGVS_18StyleContextWriterVS_19SidebarStyleContext __:0x7f8fbbd0ba80>),其是已经呈现< TtGC7SwiftUI22SheetHostingControllerVS_7AnyView :0x7f8fcbd310b0>

[Presentation] Attempt to present <TtGC7SwiftUI22SheetHostingControllerVS_7AnyView: 0x7f8fcbc49a10> on <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x7f8fcbd072c0> (from <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVVS_22_VariadicView_Children7ElementGVS_18StyleContextWriterVS_19SidebarStyleContext__: 0x7f8fbbd0ba80>) which is already presenting <TtGC7SwiftUI22SheetHostingControllerVS_7AnyView: 0x7f8fcbd310b0>.

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

Most of the code I am using is Xcode's own boilerplate code, plus common patterns borrowed from the web. Can you please help me to debug?

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

To reproduce, in Xcode 12, create a new SwiftUI iOS app using CoreData. Replace the ContentView.swift with this:

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:

Create a new 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")
                }
            }
        }
    }
}

运行时,如果您点击打开工作表",则可以点击关闭此工作表".它的工作原理.但是,如果您点击打开工作表",然后点击添加项目",将打印错误并显示取消此工作表"按钮停止工作.(您仍然可以向下滑动以消除工作表.)

When running, if you tap "Open sheet", you can then tap "Dismiss this sheet" and it works. But if you tap "Open sheet" and then tap "Add Item", the error is printed and the "Dismiss this sheet" button stops working. (You can still swipe down to dismiss the sheet.)

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

I have also tried the presentationmode.wrappedvalue.dismiss() method with no success.

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

I have found that if you comment out the ForEach loop on the main view and uncomment the Text("static text"), then adding items on the sheet no longer prints out the error or breaks dismissing of the sheet. So the problem somehow is related to presenting the data on the main sheet. But obviously I do need to actually display the data, and it seems like a really common and basic pattern. Am I doing it wrong?

推荐答案

您的 .sheet 放置在ToolbarItem上.只需在 NavigationView 上进行更改即可.

Your .sheet is placed on the ToolbarItem. Just change it on the NavigationView and it works.

这是ContentView的正文

Here is the body of the ContentView

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

            ForEach(items, id:\.self) { 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)
        }

    }
}

这篇关于SwiftUI:创建CoreData对象后无法关闭工作表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆