为什么在[moc save] PerformBlockAndWait之后我的NSManagedObject没有持久存在?

时间:2013-11-15 15:36:06

标签: ios core-data concurrency persistence nsmanagedobjectcontext

仍然使用我的RSS阅读器。

我的数据模型大致由以下NSManagedObject层次结构组成:

Category <---->> Feed <---->> Post

我的应用程序使用以下内容:

  • 具有NSManagedObjectContext并发类型的“root”NSPrivateQueueConcurrencyType。我使用此MOC将我的更改保留到NSPersistentStoreCoordinator

  • 具有NSManagedObjectContext并发类型的“main”NSMainQueueConcurrencyType。我使用这个MOC来提供我的GUI。

  • 具有NSManagedObjectContext并发类型的“本地”NSPrivateQueueConcurrencyType。每次批量获取新的Posts对象时,我都会创建并使用此MOC。

加载MainViewController后,如果为空则填充自己。

populate方法结束时,我确保所有内容都已正确保留并重新获取数据:

[_mainMOC performBlockAndWait:^{
    NSError *error;
    if (![_mainMOC save:&error]) {
        NSLog(@"[MainViewController::populate] Error.mainMOC: %@\n%@", [error description], [error userInfo]);

    }
    [[_mainMOC parentContext] performBlockAndWait:^{
        NSError *error;
        if (![[_mainMOC parentContext] save:&error]) {
            NSLog(@"[MainViewController::populate] Error.saveMOC: %@\n%@", [error description], [error userInfo]);

        }
    }];
    NSLog(@"[MainViewController::populate] OK.saveMOC");
}];
NSLog(@"[MainViewController::populate] OK.mainMOC");
[_mainMOC performBlock:^{
    NSError *error;
    if (![_mainMOC executeFetchRequest:[_fetchedResultsController fetchRequest] error:&error]) {
        NSLog(@"[MainViewController::populate] refetch: %@\n%@", [error description], [error userInfo]);

    }
}];

尽管如此,我无法在Post的专用`localMOC`中创建Feed

NSManagedObjectID *feedID=[f objectID];
if ([feedID isTemporaryID]) {
    NSLog(@"Warning %@ has not yet been persisted!", f.name);
}
/* ... */
NSManagedObjectContext *localMOC;
localMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[localMOC setParentContext:self.mainMOC];
/* ... */
[localMOC performBlock:^{
    NSError *error=nil;
    Feed *feed=((Feed *)[localMOC existingObjectWithID:feedID error:&error]);
    if (error) {
        NSLog(@"[MAsterViewController::fetchPosts] %@\n%@", [error localizedDescription], [error userInfo]);
        return;
    }
/* ... */

上面的代码产生以下日志:

2013-11-14 19:24:04.847 uRSS[10907:70b] Warning Maddox has not yet been persisted!
2013-11-14 19:24:04.847 uRSS[10907:1303] [MAsterViewController::fetchPosts] The operation couldn’t be completed. (Cocoa error 133000.)

有人能告诉我这里出了什么问题吗? 谢谢!

2 个答案:

答案 0 :(得分:1)

在没有进行某种保存/更改操作的情况下,一个上下文无法访问另一个上下文“临时”(未保存)对象。

上下文是一个暂存器,单独拥有其更改,直到它决定通过提交保存操作来共享它们(您还可以收听上下文更改通知)。

在你的情况下:
main上下文创建了一个项目(在local上下文存在之前) 然后,您尝试从local上下文访问此项,而不先将对象保留(或获取永久ID)。

为了完成这种流程,您至少需要获得对象的永久ID:[self.mainMOC obtainPermanentIDsForObjects:@[f] error:&error]

注意:
尽管main MOC是local上下文的父级,但使用existingObjectWithID:error:上下文的local方法只会查找local的已注册对象中的对象1}}上下文。否则,它会尝试从商店取货。获取永久ID将导致local上下文尝试访问商店(或父上下文)以获取对象。

答案 1 :(得分:0)

我终于通过实施自己的保存程序解决了我的问题:

[_localMOC performBlockAndWait:^{
    NSError *errLoc=nil;

    if (![self.mainMOC obtainPermanentIDsForObjects:@[[[_mainMOC insertedObjects]     arrayByAddingObjectsFromArray:[_mainMOC updatedObjects]]] error:&errLoc]) {
    NSLog(@" ... ");
    }

    if (![_localMOC save:&errLoc]) {
      NSLog(@" ... ");
    }
    [_mainMOC performBlockAndWait:^{
        NSError *errMain=nil;
        if (![_mainMOC save:&errMain]) {
            NSLog(@" ... ");
        }
    }]
}];

请注意,_mainMOC正在观察AppDelegate,并且_saveMOC父级会将其更改异步保存到磁盘。