如何将上下文连接到工作表中的持久存储协调器?

问题描述 投票:0回答:0

应用说明

我正在创建一个 swiftUI 应用程序(称为 Interval),它使用 CoreData 以一对多关系存储锻炼及其步骤。每个锻炼都有很多步骤。

查看层次结构

ContentView -> DetailView -> EditView(作为工作表)

ContentView 显示所有锻炼的列表。点击列表中的锻炼会打开 DetailView,其中会显示所选锻炼中所有步骤的列表。

在 DetailView 中,点击工具栏中的按钮会打开一个名为 EditView 的工作表,其中列出了所选锻炼中的所有步骤,并允许用户添加、删除或重新排序步骤。

问题

为了确保列表功能适用于 CoreData,我在 EditView 中使用 fetchRequest 来获取所选锻炼的所有步骤。到目前为止,我无法使用任何其他方法维护列表功能(.onDelete、.onMove)。

当我打开EditView时,弹出如下警告:

“环境中的上下文未连接到持久存储协调器:

如何删除警告,并确保我的上下文连接到持久存储协调器?

我假设 EditView 工作表会继承环境并自动连接到持久存储容器。似乎并非如此。

我的代码

IntervalApp

import SwiftUI

@main
struct IntervalApp: App {
    @StateObject var dataController = DataController()
    
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                ContentView()
                    .environment(\.managedObjectContext, dataController.container.viewContext)
            }
        }
    }
}

数据控制器

import Foundation
import CoreData
import SwiftUI

class DataController: ObservableObject {
    let container = NSPersistentContainer(name: "Interval")
    
    init() {
        container.loadPersistentStores { description, error in
            if let error = error {
                print("CoreData failed to load: \(error.localizedDescription)")
            }
        }
    }
}

内容视图

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(fetchRequest: Workout.all()) private var workouts
    
    var body: some View {
        List {
            ForEach(workouts) { workout in
                NavigationLink {
                    DetailView(workout: workout)
                } label: {
                    Text(workout.title)
                }
            }
        }
        .navigationTitle("Workouts")
    }
}

细节视图

import SwiftUI

struct DetailView: View {
    @Environment(\.dismiss) var dismiss
    @Environment(\.managedObjectContext) var moc
    @ObservedObject var workout: Workout
    @State private var showSheet: Bool = false
    
    var body: some View {
        List {
            // list steps
        }
        .navigationBarTitle(workout.title)
        .toolbar {
            ToolbarItemGroup(placement: .navigationBarTrailing) {
                Button {
                    showSheet.toggle()
                } label: {
                    Label("Edit", systemImage: "square.and.pencil")
                }
            }
        }
        .sheet(isPresented: $showSheet) {
            NavigationStack {
                EditView(workout: workout)
                    //.environment(\.managedObjectContext, moc) -> this did not work
            }
        }
    }
}

编辑视图

import SwiftUI
import CoreData

struct EditView: View {
    @Environment(\.dismiss) var dismiss
    @Environment(\.managedObjectContext) var moc
    @ObservedObject private var workout: Workout
    @FetchRequest private var steps: FetchedResults<Step>
    
    init(workout: Workout) {
        self.workout = workout
        _steps = FetchRequest(
            entity: Step.entity(),
            sortDescriptors: [ NSSortDescriptor(keyPath: \Step.index, ascending: true) ],
            predicate: NSPredicate(format: "workout == %@", workout)
        )
    }
    
    var body: some View {
        List {
            Section {
                ForEach(steps) { step in
                    // list steps
                }
                //.onDelete()
                //.onMove()
            } header: {
                Text("Steps")
            }
        }
        .navigationTitle("Edit workout")
        .toolbar {
            ToolbarItem(placement: .confirmationAction) {
                Button {
                    // save
                    dismiss()
                } label: {
                    Text("Save")
                }
            }
        }
    }
}

我试过将环境从 DetailView 传递到 EditView 工作表,如下所示:

.sheet(isPresented: $showSheet) {
    NavigationStack {
        EditView(workout: workout)
            .environment(\.managedObjectContext, moc) // Adding this did not work
    }
}

...但是没有用。

swiftui core-data swiftui-environment nspersistentcontainer
© www.soinside.com 2019 - 2024. All rights reserved.