我正在使用UIManagedDocument来获取核心数据。我的managedObjectContext中有Calendar对象,具有calendarSelected
属性。 Calendar实体与CalendarEntry具有多对多关系。
当我更改其calendarSelected
属性然后执行NSFetchRequest以获取具有以下谓词的CalendarEntry对象时:
[NSPredicate predicateWithFormat:@"calendar.calendarSelected = YES"]
如果没有我调用
,calendar.calendarSelected似乎没有看到我所做的更改 [myManagedDocument saveToURL:myManagedDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {}];
第一。我在某处读到,从同一个上下文中获取内容应该遵循在该上下文中所做的更改,即使更改尚未写入持久性存储。我错过了什么?
更新
当calendarEvents关系是一个错误时,它似乎正在发生:calendarEvents = "<relationship fault: 0x91aec90 'calendarEvents'>";
但是当关系不是错误时就会起作用。
答案 0 :(得分:1)
如果问题仅出现在多对多关系所指向的新插入的CalendarEntry对象上,那么它们可能还没有永久对象ID。这很容易调试,只需转储对象ID并检查它是暂时的还是永久的。
我已经看到当保留to-many关系中的包含对象时会发生这种情况;似乎只要它被保留,关系中的多对象包含的对象永远不会到达他们获得永久ID的点。通过将应用程序放在后台并重新启动它,可以轻松调试;后台处理通常会强制UIManagedDocument保存,然后事情将按照您的预期开始工作,因为CalendarEntry实体将被分配永久ID,因此将成为可获取的。
就保存UIManagedDocument而言,您无法控制在使用UIManagedDocument时何时会发生这种情况。最好的办法是通过updateChangeCount:UIDocumentChangeDone安排将来发生保存,但同样,它会“很快”发生,但不是确定性的,即,它不可能知道它何时会发生。
要解决临时与永久对象ID问题,如果这是您所看到的,请在NSManagedObjectContext上尝试以下类别;在完成插入新的CalendarEntry对象后调用它,以强制解决问题。
// Obtain permanent ids for any objects that have been inserted into
// this context.
//
// As of this writing (iOS 5.1), we need to manually obtain permanent
// ids for any inserted objects prior to a save being performed, or any
// objects that are currently retained, that have relationships to the
// inserted objects, won't be updated with permanent ids for the related
// objects when a save is performed unless the retained object is refetched.
// For many objects, that will never occur, so we need to force the issue.
- (BOOL)obtainPermanentIDsForInsertedObjects:(NSError **)error
{
NSSet * inserts = [self insertedObjects];
if ([inserts count] == 0) return YES;
return [self obtainPermanentIDsForObjects:[inserts allObjects]
error:error];
}
答案 1 :(得分:0)
基本上,在进行任何更改后,您必须使用撤消管理器,或者调用[document updateChangeCount:UIDocumentChangeDone];就这样!任何其他“保存”调用都会在其他地方破坏其他东西。
规范的更新方法应该是......
你知道你在主线上
NSManagedObjectContext *ctx = document.managedObjectContext;
// Do stuff with it
[document updateChangeCount:UIDocumentChangeDone];
你在不同的线程
[document.managedObjectContext performBlock:^{
// Do stuff with it on the main thread
[document updateChangeCount:UIDocumentChangeDone];
}];
OR
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
moc.parentContext = document.managedObjectContext;
[moc performBlock:^{
// Do stuff with it on a background thread
// Push changes up to parent (which is the document's main MOC)
// The document will know it's dirty and save changes
[moc save:&error];
}];
或者如果你想在后台线程中进行更改,而不是弄乱主文档MOC,那么就在父文件上执行...主要的MOC在下一次获取之前不会看到它们。
[document.parentContext.managedObjectContext performBlock:^{
// Do stuff with it on a background thread, but the main MOC does not
// see the changes until it does a fetch.
}];