0

我正在为核心数据使用 UIManagedDocument。我的 managedObjectContext 中有日历对象,它们有一个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'>";但在关系没有故障时起作用。

4

2 回答 2

1

如果问题仅出现在由一对多关系指向的新插入的 CalendarEntry 对象上,那么它们可能还没有永久对象 ID。这很容易调试,只需转储对象 ID 并检查它是临时的还是永久的。

当保留一对多关系中的包含对象时,我已经看到了这种情况;似乎只要保留它,关系中的多对包含对象就永远不会达到它们获得永久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];
}
于 2012-04-19T23:52:55.860 回答
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];
}];

或者

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.
}];
于 2012-04-12T02:54:51.027 回答