我有一个应用程序,其中有两个托管对象上下文设置如下:
当将新的托管对象插入主上下文时,我保存主上下文,然后保存父上下文,如下所示:
[context performBlockAndWait:^{
NSError * error = nil;
if (![context save: &error]) {
NSLog(@"Core Data save error %@, %@", error, [error userInfo]);
}
}];
[parentContext performBlock:^{
NSError *error = nil;
BOOL result = [parentContext save: &error];
if ( ! result ) {
NSLog( @"Core Data save error in parent context %@, %@", error, [error userInfo] );
}
}];
我的理解是,首次创建管理对象时,它具有临时objectID
。然后保存主上下文,并且此对象及其临时ID将转到父上下文。然后保存父上下文。保存最后一个上下文后,父上下文中的临时objectID
将转换为永久objectID
。
所以:
[NSManagedObjectContext obtainPermanentIDsForObjects:error:]
,然后对应用程序进行后台处理,重新激活它,重新加载,使用主要上下文objectWithID:
获取对象,并访问属性,我得
“CoreData无法解决......”。
答案 0 :(得分:42)
这是一个已知的错误,希望很快得到解决,但一般来说,获取永久ID就足够了,只要您在第一个子项中保存数据之前这样做,并且只包含插入的对象:
[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:&error]
在某些复杂情况下,最好在创建实例后立即获取永久ID,尤其是在您有复杂关系的情况下。
您如何以及何时致电obtainPermanentIDsForObjects
?
我没有关注应用程序崩溃的部分。也许更好的解释会有所帮助。
答案 1 :(得分:10)
正如Jody所说,当使用子ManagedObjectContext在后台线程中创建新的NSManagedObject时,您必须通过在保存之前执行以下操作来强制创建永久ID:
NSError *error = nil;
[threadedMOC obtainPermanentIDsForObjects:threadedMOC.insertedObjects.allObjects error:&error];
BOOL success = [threadedMOC save:&error];
恕我直言,这样做并不是很直观 - 毕竟,在你保存之前,你要求永久身份证!但这是它似乎工作的方式。如果您在保存后要求提供永久ID,则该ID仍然是临时的。在Apple Docs中,您实际上可以使用以下内容来确定对象的ID是否是临时的:
BOOL isTemporary = [[managedObject objectID] isTemporaryID];
答案 2 :(得分:1)
Swift中的iOS 8.3解决方案仍然存在问题:
func saveContext(context: NSManagedObjectContext?){
NSOperationQueue.mainQueue().addOperationWithBlock(){
if let moc = context {
var error : NSError? = nil
if !moc.obtainPermanentIDsForObjects(Array(moc.insertedObjects), error: &error){
println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)")
}
if moc.hasChanges && !moc.save(&error){
println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)")
}
}
}
}
func saveBackgroundContext(){
saveContext(self.defaultContext)
privateContext?.performBlock{
var error : NSError? = nil
if let context = self.privateContext {
if context.hasChanges && !context.save(&error){
println("\(__FUNCTION__)\n \(error?.localizedDescription)\n \(error?.userInfo)")
}else {
println("saved private context to disk")
}
}
}
}
其中: