与核心数据一起使用时预览崩溃
Posted
技术标签:
【中文标题】与核心数据一起使用时预览崩溃【英文标题】:Previews crashing when using with core-data 【发布时间】:2020-08-29 12:23:53 【问题描述】:我正在尝试使用 swiftui 和 core-data 创建一个简单的待办事项应用程序,但是在添加视图时遇到了一些问题。我有一个TaskView
视图,它将用于显示有关列表中任务的一些信息(标题、日期等)。但是,当尝试使用演示 Task
对象为视图创建预览时,预览会崩溃(正在运行的应用程序仍然有效)。
对不起,如果这是一个微不足道的问题,对于 swift 和一般编程来说都是新手。
TaskView.swift
import SwiftUI
struct TaskView: View
@Environment(\.managedObjectContext) var managedObjectContext
var task: Task
var body: some View
HStack
Image(systemName: task.checked == true ? "circle" : "checkmark.circle.fill")
VStack
Text(task.name ?? "unknown name")
Text(String(task.streak))
struct TaskView_Previews: PreviewProvider
static var previews: some View
let task = Task()
task.name = "Washing up"
task.desc = "Wash the dishes"
task.checked = false
task.streak = 2
return TaskView(task: task)
.previewLayout(.fixed(width: 375, height: 60))
ContentView.swift
import SwiftUI
struct ContentView: View
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Task.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Task.checked, ascending: false),
NSSortDescriptor(keyPath: \Task.name, ascending: true)
]) var tasks: FetchedResults<Task>
var body: some View
NavigationView
List
ForEach(tasks, id: \.self) task in
TaskView(task: task).environment(\.managedObjectContext, self.managedObjectContext)
.onDelete(perform: deleteTask)
.navigationBarTitle("Today")
func deleteTask(at indexSet: IndexSet)
indexSet.forEach TaskUtils.delete(task: tasks[$0], using: self.managedObjectContext)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
您无法在没有上下文的情况下创建核心数据对象,因此请考虑使用协议/模拟方法来测试/预览没有数据库对象的视图。 【参考方案1】:我通过添加首先设置上下文常量然后使用 init 初始化您在预览中使用的任务常量来修复您的 TaskView
import SwiftUI
struct TaskView: View
@Environment(\.managedObjectContext) var managedObjectContext
var task: Task
var body: some View
HStack
Image(systemName: task.checked == true ? "circle" : "checkmark.circle.fill")
VStack
Text(task.name ?? "unknown name")
Text(String(task.streak))
struct TaskView_Previews: PreviewProvider
static var previews: some View
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext // IMPORTANT
let task = Task.init(context: context) // IMPORTANT
task.name = "Washing up"
task.desc = "Wash the dishes"
task.checked = false
task.streak = 2
return TaskView(task: task).environment(\.managedObjectContext, context)
.previewLayout(.fixed(width: 375, height: 60))
至于您的 ContentView,我做了一些小改动以使其正常工作 - 添加了一个按钮以将对象添加到 CoreData 模型。
import SwiftUI
struct ContentView: View
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Task.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Task.checked, ascending: false),
NSSortDescriptor(keyPath: \Task.name, ascending: true)
]) var tasks: FetchedResults<Task>
var body: some View
NavigationView
List
ForEach(tasks, id: \.self) task in
TaskView(task: task).environment(\.managedObjectContext, self.managedObjectContext)
//.onDelete(perform: deleteTask)
.navigationBarTitle("Today")
.navigationBarItems(trailing:
Button("Add")
let task = Task(context: self.managedObjectContext)
task.name = "Washing up"
task.desc = "Wash the dishes"
task.checked = false
task.streak = Int32(Int.random(in: 0...10))
try? self.managedObjectContext.save()
)
// func deleteTask(at indexSet: IndexSet)
// indexSet.forEach TaskUtils.delete(task: tasks[$0], using: self.managedObjectContext)
//
struct ContentView_Previews: PreviewProvider
static var previews: some View
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return ContentView().environment(\.managedObjectContext, context)
【讨论】:
您的 CoreData 实体的名称是什么?那是“任务”吗? 是的,没错。如果有帮助,我还添加了我的 ContentView 代码 我已经修改好了,试一试以上是关于与核心数据一起使用时预览崩溃的主要内容,如果未能解决你的问题,请参考以下文章
使用 SwiftUI @Binding 预览崩溃:与应用程序的通信中断
Xcode如何在预览(Preview)调试中避免与SwiftUI正常运行时环境不一致导致的崩溃
Xcode如何在预览(Preview)调试中避免与SwiftUI正常运行时环境不一致导致的崩溃
Xcode 12.2+生成SwiftUI 2.0 CoreData模板预览时崩溃问题的解决