ios - CoreData 和 SwiftUI:保存 NSManagedObjectContext 时出错
问题描述
编辑:我得到的错误是nilError
代码0
编辑:这是一个简单的、最低限度可行的应用程序,它演示了这个问题:
@main
struct CoreDataTestApp: App {
let persistantContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Model")
container.loadPersistentStores { _, error in
if let error = error {
fatalError(error.localizedDescription)
}
}
return container
}()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistantContainer.viewContext)
}
}
}
struct ModalView: View {
@Binding var isPresented: Bool
@Environment(\.managedObjectContext) var managedObjectContext
var body: some View {
Button("Add Event") {
let event = Event(context: managedObjectContext)
event.name = "Hello"
event.startDate = Date()
event.endDate = Date().addingTimeInterval(86400)
event.colorIndex = 0
event.id = UUID()
try! managedObjectContext.save()
self.isPresented = false
}
}
}
struct ContentView: View {
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(
entity: Event.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \Event.endDate, ascending: true)
]
) var events: FetchedResults<Event>
@State var isPresented: Bool = false
var body: some View {
NavigationView {
List {
ForEach(events, id: \.id) { event in
Text(event.name!)
}
}
.navigationTitle("List")
.navigationBarItems(trailing: Button("Modal") {
self.isPresented = true
})
}
.sheet(isPresented: $isPresented) {
ModalView(isPresented: $isPresented)
}
}
}
我正在 SwiftUI 2.0 中构建一个简单的倒计时时钟应用程序。最初,我将数据存储在 UserDefaults 中,但现在我正尝试将我的模型迁移到以前没有使用过的 CoreData。当我尝试保存时NSManagedObjectContext
,我收到一条错误消息The operation couldn't be completed
,并且我的模型永远不会更新,视图也不会更新,我不确定这是为什么。
这是我的主要应用程序结构:
@main
struct HourglassApp: App
let container: NSPersistentContainer = {
let pc = NSPersistentContainer(name: "Model")
pc.loadPersistentStores { _, error in
if let error = error {
fatalError(error.localizedDescription)
}
}
return pc
}()
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, container.viewContext)
}
}
}
这是我的 AddEventView:
struct AddEventView: View {
@State var eventName: String = ""
@State var endDate = Date().addingTimeInterval(60)
@State var isAddedToCalendar = true
@State var gradientIndex: Int = 0
@Binding var showModal: Bool
@Environment(\.managedObjectContext) var context: NSManagedObjectContext
let existingEvent: Event?
var body: some View {
NavigationView {
Form {
Section {
HStack {
Text("Event Name")
TextField("New Year's Day", text: $eventName)
.multilineTextAlignment(.trailing)
}
DatePicker(
"Event Date ",
selection: $endDate,
in: Date()...,
displayedComponents: [.date, .hourAndMinute]
)
}
Section {
ColorChooser(linearGradients, selectedIndex: $gradientIndex).padding(.vertical, 8)
Toggle("Add to Calendar", isOn: $isAddedToCalendar)
.toggleStyle(SwitchToggleStyle(tint: accentColor))
}
}
.navigationBarItems(
leading: Button(action: {
self.showModal.toggle()
}) {
Text("Cancel").foregroundColor(accentColor)
}, trailing: Button(action: {
let adjustedEnd = Calendar.current.date(bySetting: .second, value: 0, of: endDate)!
DataProvider.shared.removeEvent(existingEvent, from: context)
DataProvider.shared.addEvent(
in: context,
name: eventName,
range: (existingEvent?.startDate ?? Date())...adjustedEnd,
colorIndex: gradientIndex,
shouldAddToCalendar: isAddedToCalendar
)
self.showModal.toggle()
}) {
Text("Add").bold().foregroundColor(accentColor)
}
.onAppear {
if let event = existingEvent {
self.eventName = event.name!
self.endDate = event.endDate!
self.gradientIndex = Int(event.colorIndex)
}
}
}
}
}
这是我的 DataProvider 类:
class DataProvider {
static let shared = DataProvider()
static func allEventsFetchRequest() -> NSFetchRequest<Event> {
let request: NSFetchRequest<Event> = Event.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: Defaults.shared.comparatorKey, ascending: true)]
return request
}
func addEvent(in context: NSManagedObjectContext, name: String, range: ClosedRange<Date>, colorIndex: Int, shouldAddToCalendar inCalendar: Bool) {
let event = Event(context: context)
event.name = name
event.startDate = range.lowerBound
event.endDate = range.upperBound
event.colorIndex = Int16(colorIndex)
event.id = UUID()
UserNotifications.shared.registerEventNotification(event)
if inCalendar {
UserCalendar.shared.addEvent(event) { _ in }
}
do {
try context.save()
} catch {
fatalError(error.localizedDescription)
}
}
func removeEvent(_ event: Event?, from context: NSManagedObjectContext) {
guard let event = event else { return }
context.delete(event)
UserNotifications.shared.unregisterEventNotification(event)
UserCalendar.shared.removeEvent(event) { _ in }
do {
try context.save()
} catch {
fatalError(error.localizedDescription)
}
}
}
同样,在我显示所有事件的主 ContentView 中,我有
@FetchRequest(
fetchRequest: DataProvider.allEventsFetchRequest()
) var events: FetchedResults<Event>
@Environment(\.managedObjectContext) var context: NSManagedObjectContext
我尝试使用类似的习语开发一个最小可行的 CoreData 示例应用程序,并且效果很好,所以我不确定这里有什么问题。
任何帮助将不胜感激,谢谢!
解决方案
推荐阅读
- r - 从 excel 运行 RScript 权限被拒绝 错误代码 70
- c# - 使用 wshttpbinding 的 WCF 用户名和密码验证不起作用
- java - 如何将 GSON 库中的 JSON 字符串转换为 JSON 对象?
- php - 在 POST API 中使用 guzzle 时出现问题如何解决?
- flutter - Flutter GridView item wrap_content 高度
- php - sql 命令成功后刷新页面
- google-sheets - 有没有办法将 YouTube 播放列表中的视频名称导入 Google 表格?
- javascript - 如果存储为对象,如何检索数据?
- class - 公共方法中的私有方法
- c++ - 类/结构/联合中的匿名类/结构/联合是什么意思?