【发布时间】:2018-05-23 19:26:15
【问题描述】:
我有很多数据存储在 Core Data 中,没有任何问题。现在我需要添加一些额外的数据。我决定使用要存储的对象(及其所有子对象)实现NSCoding,而不是将对象存储为Transformable(NSObject),而不是为所有这些新数据创建实体。我以前做过这个(在 Obj-c 中),但由于某种原因,这次我不能让它工作。
假设我有一个名为Event:NSObject,NSCoding 的巨大类,其中包含名称、日期和一吨的附加变量。然后想象一下,您希望能够让用户在活动开始前的给定天数收到通知。比如,让用户“观看”事件。我想跟踪正在观看哪些事件,以及我应该在多长时间之前发送通知。有了这个,我可以获得所有“观看”事件的列表,并知道他们想要通知的事件前多少天。这只是真实情况的一个不好的例子,请耐心等待。不要考虑“通知”部分,只是存储数据。
我有我的Event-object,现在我在我的CoreData-database 中创建了一个WatchEvent-entity,它有两个属性:event:Transformable 和days:Integer。两者都不是可选的。
我的整个 Event-class 及其所有子类现在都实现了 NSCoding,因此要将其存储在数据库中,我只需将其设置为可转换属性。在这里您可以看到我如何创建WatchEvent-object 并将其放入数据库,以及从数据库中获取所有WatchEvents 的函数,以及打印每个WatchEvent 内容的函数。
func storeWatchEvent(someEvent:Event, numberOfDays:Int){
let watchEvent = WatchEvent(entity: NSEntityDescription.entity(forEntityName: "WatchEvent", in: managedObjectContext)!, insertInto: managedObjectContext)
watchEvent.days = numberOfDays //e.g 3
watchEvent.event = someEvent
saveContext()
}
func saveContext(){
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func getWatchedEvents()->[WatchEvent]?{
return managedObjectContext.fetch(WatchEvent.fetchRequest())
}
func printOutAllWatchedEvents(){
if let watchedEvents = getWatchedEvents(){
watchedEvents.foreach{ (w) in
print("numberOfDays: ", w.days)
print("event: ", w.event)
}
}
}
func saveButtonClicked(){
storeWatchEvent(someEvent, numberOfDays:3)
// For testing, attempt to get all my events immediately, several times
printOutAllWatchedEvents() //Prints out `numberOfDays: 3` and a valid `event` correctly
printOutAllWatchedEvents() //Prints out `numberOfDays: 3` and a valid `event` correctly
printOutAllWatchedEvents() //Prints out `numberOfDays: 3` and a valid `event` correctly
}
func verifyButtonClicked(){
printOutAllWatchedEvents() //Prints out `numberOfDays: 3` and `nil` for event.
}
假设我有两个按钮。一个“保存”和另一个“验证”。如果单击“保存”,我会保存有效对象,正如您在代码中看到的那样,我会立即在数据库中查询所有存储的 WatchEvent,并将它们打印出来。那时,一切看起来都很好。如果我单击“验证”按钮,它应该打印出相同的内容,但它删除了我的event。它设法保持days-attribute 被存储,但该事件被删除。为什么?:(
等待多长时间单击验证按钮并不重要。如果我几乎同时单击它们,这仍然会发生。
我在 saveButtonClick 中调用了 printOutAllWatchedEvents 三次,由于它每次都设法返回一个有效的事件对象,我假设其中的存储/NSCoding 部分是成功的?
但是,如果我单击验证按钮,我认为这至少会在几个“运行循环”之后发生,可转换的 event-object 已被删除..
我不知道发生了什么。
为什么如果我在插入它们后立即请求它们,它会设法返回我的有效事件,但如果我稍后再请求它们则不会?为什么这只影响transformable 对象?整数days 正确保留给所有WatchEvents。而且由于我已将event 标记为 not 可选,它如何返回 nil 并且从不给我任何错误?我在上下文中调用save 时没有错误,我已经检查过了。
【问题讨论】:
-
由于您的问题与保存方式有很大关系,因此可以将真实代码替换为
do/try managedObjectContext.save() else print out error etc. etc. -
@AlecO 你是对的。现在添加。而且它永远不会打印出任何保存错误。
-
首先,检查您的数据库是否存储在存储协调器 (SQL) 文件中的数据现实,这可能是因为您存储和获取的上下文不同?
-
我不知道我在寻找什么。我已经下载了一个工具来检查实际的 SQLite 文件,并且我看到了我所有的 WatchEvent 对象,并且
event字段是 empty。我认为这是因为它以某种方式被删除了,因为如果我立即查询它,我确实会在上面的代码中返回它,但也许它根本不会被存储,当我查询它时我收到的是某种缓存? @IraniyaNaynesh 您提供的链接与我的问题完全相反。一开始看不到存储的对象,但后来得到它。我一开始可以看到他们,但以后再也看不到了。会调查。