gpt4 book ai didi

ios - 如何在 SwiftUI 环境中实现子上下文(CoreData)?

转载 作者:行者123 更新时间:2023-12-01 16:20:32 25 4
gpt4 key购买 nike

我目前正在学习 SwiftUI,以进一步将其包含在我的日常基于 UIKit 的工作流程中。我已经到了无法在 SwiftUI 中运行一个概念的地步,我已经在 UIKit 中使用了多年。

这个想法是使用我的主要 CoreData managedObjectContext 的子上下文用于编辑实体。我基本上通过执行以下操作来实现它:

// Get view context of application
let viewContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

// Create NSManagedObjectContext
let editingContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

// Set the parent of the editing context to the main view context
editingContext.parent = viewContext

通过使用单独的 editingContext我可以对其中的实体进行更改,而无需直接对我的主要上下文进行更改。如果用户选择中止更改,我只需重置 editingContext .

对于 SwiftUI 中的实现,我选择通过创建自定义 EnvironmentKey 将 editorContext 实现为环境对象。 :
struct EditingContextKey: EnvironmentKey {
static let defaultValue: NSManagedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
}

extension EnvironmentValues {
var editingContext: NSManagedObjectContext {
get {
return self[EditingContextKey.self]
}
set {
self[EditingContextKey.self] = newValue
}
}
}

然后 editingContext被添加到我的 Root View 中:
let contentView = ContentView()
.environment(\.managedObjectContext, viewContext)
.environment(\.editingContext, editingContext)

至此,一切正常。我也可以使用 editingContext通过在各自的 View 中调用以下命令。
@Environment(\.editingContext) var editingContext

但是,一旦我对 editingContext 中的实体进行了更改,并尝试保存 editingContext ,我收到一个意外错误:
Fatal error: Unresolved error Error Domain=Foundation._GenericObjCError Code=0 "(null)", [:]: file

我已经检查过了,如果编辑实体的上下文匹配 editingContext .情况似乎如此。我有感觉,它可能与 SwiftUI 中的绑定(bind)有关,但不知道如何找到解决方案。

有没有人遇到过类似的问题?或者我对所需功能的基本方法是错误的,有更方便的方法吗?

谢谢!

最佳答案

我正在使用这样的子上下文:

struct ItemEditorConfig: Identifiable {
let id = UUID()
let context: NSManagedObjectContext
let item: Item

init(viewContext: NSManagedObjectContext, objectID: NSManagedObjectID) {
// create the scratch pad context
context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.parent = viewContext
// load the item into the scratch pad
item = context.object(with: objectID) as! Item
}
}

struct ItemEditor: View {
@ObservedObject var item: Item // this is the scratch pad item
@Environment(\.managedObjectContext) private var context
@Environment(\.dismiss) private var dismiss // causes body to run
let onSave: () -> Void
@State var errorMessage: String?

var body: some View {
NavigationView {
Form {
Text(item.timestamp!, formatter: itemFormatter)
if let errorMessage = errorMessage {
Text(errorMessage)
}
Button("Update Time") {
item.timestamp = Date()
}
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
// first save the scratch pad context then call the handler which will save the view context.
do {
try context.save()
errorMessage = nil
onSave()
} catch {
let nsError = error as NSError
errorMessage = "Unresolved error \(nsError), \(nsError.userInfo)"
}
}
}
}
}
}
}

struct EditItemButton: View {
let itemObjectID: NSManagedObjectID
@Environment(\.managedObjectContext) private var viewContext
@State var itemEditorConfig: ItemEditorConfig?

var body: some View {
Button(action: edit) {
Text("Edit")
}
.sheet(item: $itemEditorConfig, onDismiss: didDismiss) { config in
ItemEditor(item: config.item) {
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
itemEditorConfig = nil // dismiss the sheet
}
.environment(\.managedObjectContext, config.context)
}
}

func edit() {
itemEditorConfig = ItemEditorConfig(viewContext: viewContext, objectID: itemObjectID)
}

func didDismiss() {
// Handle the dismissing action.
}
}

struct DetailView: View {
@ObservedObject var item: Item

var body: some View {
Text("Item at \(item.timestamp!, formatter: itemFormatter)")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditItemButton(itemObjectID: item.objectID)
}
}
}
}

关于ios - 如何在 SwiftUI 环境中实现子上下文(CoreData)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60977658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com