Kev*_*ats 31 core-data swift swiftui
我正在尝试通过构建作业管理应用程序来自学 Core Data。我的代码构建良好,应用程序运行正常,直到我尝试向列表添加新分配。我得到这个错误Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1c25719e8)以下行:ForEach(courses, id: \.self) { course in。控制台也有这个错误:Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x2823cb3a0>。
我对 Core Data 知之甚少,不知道可能是什么问题。我在数据模型中设置了“作业”和“课程”实体,其中课程与作业具有一对多关系。每个作业将被归类到特定的课程下。
这是向列表添加新分配的视图的代码:
struct NewAssignmentView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Course.entity(), sortDescriptors: []) var courses: FetchedResults<Course>
@State var name = ""
@State var hasDueDate = false
@State var dueDate = Date()
@State var course = Course()
var body: some View {
NavigationView {
Form {
TextField("Assignment Name", text: $name)
Section {
Picker("Course", selection: $course) {
ForEach(courses, id: \.self) { course in
Text("\(course.name ?? "")").foregroundColor(course.color)
}
}
}
Section {
Toggle(isOn: $hasDueDate.animation()) {
Text("Due Date")
}
if hasDueDate {
DatePicker(selection: $dueDate, displayedComponents: .date, label: { Text("Set Date:") })
}
}
}
.navigationBarTitle("New Assignment", displayMode: .inline)
.navigationBarItems(leading: Button(action: {
self.presentationMode.wrappedValue.dismiss()
}, label: { Text("Cancel") }),
trailing: Button(action: {
let newAssignment = Assignment(context: self.moc)
newAssignment.name = self.name
newAssignment.hasDueDate = self.hasDueDate
newAssignment.dueDate = self.dueDate
newAssignment.statusString = Status.incomplete.rawValue
newAssignment.course = self.course
self.presentationMode.wrappedValue.dismiss()
}, label: { Text("Add").bold() }))
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:这是 AppDelegate 中设置持久容器的代码:
lazy var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "test")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
Run Code Online (Sandbox Code Playgroud)
以及设置环境的 SceneDelegate 中的代码:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
// 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 = ContentView().environment(\.managedObjectContext, context)
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
Run Code Online (Sandbox Code Playgroud)
maw*_*wus 42
像您的 moc 这样的环境值只会自动传递给层次结构中的其他视图。因此,如果您显示工作表或任何不属于您的视图层次结构的内容,您将失去环境,并且您需要将 moc 传递给新的层次结构,就像您为 ContentView 所做的那样。检查此代码片段:
.sheet(isPresented: self.$showSheet) {
SheetView()
.environment(\.managedObjectContext, self.moc)
}
Run Code Online (Sandbox Code Playgroud)
您实际上并没有保存上下文。您应该执行以下操作:
let newAssignment = Assignment(context: self.moc)
newAssignment.name = self.name
newAssignment.hasDueDate = self.hasDueDate
newAssignment.dueDate = self.dueDate
newAssignment.statusString = Status.incomplete.rawValue
newAssignment.course = self.course
do {
try self.moc.save()
} catch {
print(error)
}
Run Code Online (Sandbox Code Playgroud)
你@FetchRequest(...)也可以看起来像这样:
@FetchRequest(fetchRequest: CourseItem.getCourseItems()) var courses: FetchedResults<CourseItem>
Run Code Online (Sandbox Code Playgroud)
你可以修改你的CourseItem类来处理sortDescriptors如下:
public class CourseItem: NSManagedObject, Identifiable {
@NSManaged public var name: String?
@NSManaged public var dueDate: Date?
// ...etc
}
extension CourseItem {
static func getCourseItems() -> NSFetchRequest<CourseItem> {
let request: NSFetchRequest<CourseItem> = CourseItem.fetchRequest() as! NSFetchRequest<CourseItem>
let sortDescriptor = NSSortDescriptor(key: "dueDate", ascending: true)
request.sortDescriptors = [sortDescriptor]
return request
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以修改ForEach(...)以下内容,也可以很容易地处理项目的删除:
ForEach(self.courses) { course in
// ...
}.onDelete { indexSet in
let deleteItem = self.courses[indexSet.first!]
self.moc.delete(deleteItem)
do {
try self.moc.save()
} catch {
print(error)
}
}
Run Code Online (Sandbox Code Playgroud)
您要确保的一件事是“班级名称”设置为“CourseItem”,它与CourseItem我们之前创建的班级相匹配。
只需点击实体在您的.xcdatamodeId文件,并设置一切以下(含模块到“当前产品模块”和代码生成“手动/无”):
| 归档时间: |
|
| 查看次数: |
8713 次 |
| 最近记录: |