NSFetchRequest没有看到NSManagedObjectContext中关系的更改

时间:2012-04-11 22:35:42

标签: ios core-data

我正在使用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'>";但是当关系不是错误时就会起作用。

2 个答案:

答案 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.
}];