NSFetchedResultsController不显示来自不同上下文的更新

Lor*_*o B 22 core-data nsfetchedresultscontroller nsoperationqueue nsmanagedobjectcontext ios

我有一个NSFetchedResultsController和几个操作更新托管对象在不同的​​线程上通过NSOperationQueue.

FRC(带有谓词)看起来像这样:

- (NSFetchedResultsController*)fetchedResultsController
{
    if(fetchedResultsController) return fetchedResultsController;

    NSManagedObjectContext* mainContext = [self managedObjectContext];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Check" inManagedObjectContext:mainContext]];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"isSync == %@", [NSNumber numberWithBool:NO]]];
    [fetchRequest setFetchBatchSize:10];

    fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:mainContext sectionNameKeyPath:nil cacheName:nil];
    fetchedResultsController.delegate = self;

    [fetchRequest release], fetchRequest = nil;

    return fetchedResultsController;
}
Run Code Online (Sandbox Code Playgroud)

主线程和线程操作具有自己的托管对象上下文.他们只共享同一个协调员.

在线程操作中,我将isSync属性从更改NOYES.要知道Check要更新的实体是什么,主要上下文将传递给线程化的a NSManagedObjectID.线程操作检索托管对象,如下所示:

-(void)main
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    NSManagedObjectContext *exportContext = [[NSManagedObjectContext alloc] init];
    [exportContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];

    //...

    Check* check = (Check*)[exportContext existingObjectWithID:objID error:&error];
    check.isSync = [NSNumber numberWithBool:YES];

    //...

    [exportContext save:&error];

    [pool release], pool = nil;
}
Run Code Online (Sandbox Code Playgroud)

当线程操作调用savemergeChangesFromContextDidSaveNotification通知,被称为与主背景融合了变化.

- (void)contextChanged:(NSNotification*)notification
{
    if ([notification object] == [self managedObjectContext]) return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
        return;
    }

    [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
Run Code Online (Sandbox Code Playgroud)

记录notification潜在客户的描述以验证是否正确执行了更改.

我的问题

代理方法NSFetchedResultsControllerDelegate没有被调用.

这很奇怪,因为处理相同的上下文,主要的,允许侦听更改和委托方法被调用,例如删除行中的对象UITableView.

我在SO上找到了一些有同样问题的主题.我已经尝试了所有的解决方法,但我找不到有价值的解决方案:

  1. NSFetchedResultsController不显示来自其他上下文的更新

  2. 从后台线程合并更新后,NSFetchedResultsController不会触发委托方法

  3. 带谓词的NSFetchedResultsController忽略从不同NSManagedObjectContext合并的更改

先感谢您.

编辑

上面的代码在之前的模型中工作.然后我创建了一个新模型复制(和粘贴)前一个实体,现在它不再工作了.

建议?

编辑2

这是我在NSFetchedResultsControllergetter中使用的谓词.这是我的错,但是当我写这篇文章时,我没有复制它.

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"insertionDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

// previous code here
[fetchRequest setSortDescriptors:sortDescriptors];
Run Code Online (Sandbox Code Playgroud)

现在,关于Jody的最后评论

在NSOperation的main()中,您正在加载新对象,并且在那里看起来您正在为每个新对象将isSync设置为YES.您用于fetchedResultsController的谓词仅查找具有isSync == NO的对象.

我希望当属性isSync设置为YES时,NSFetchedResultsController观察到更改并删除与谓词不匹配的行.我错了吗?

请记住,当将更改从背景合并到主线程时,我能够看到很少有对象更新了它们的isSync属性.

Jod*_*ins 11

你有基本的想法,所以你的代码中可能存在一个错误......

仔细检查您是否正确注册以接收来自后台MOC的通知.

注册以接收来自所有对象的所有通知.在该方法中,记录事件及其所有数据.当对象是MOC时,转储其所有属性(尤其是已注册,已插入,已更新和已删除对象的列表).

在保存调用之前和之后放置一个日志语句,并在通知处理程序中合并通知.

此外,您省略了很多代码,因此很难知道您实际在做什么,但是您包含的代码示例看起来很难将所有正在加载的对象的isSync设置为YES,但是您的获取请求只需要设置了isSync的那些没有.这些新对象都不会传递该谓词.

最后,仔细检查您的模型定义并确保使用正确的数字类型.这可能是问题的重要来源.

编辑

哦是的,我忘了...你的获取请求没有排序描述符.创建FRC时,您的获取请求必须至少包含一个排序描述符...如果您有多个部分,则使用第一个排序描述符将对象分组为多个部分.

跟进Alexsander的评论......我在帖子的开头提到了它,但是你肯定不想听MOC的通知,除非它是众所周知的(当然,除非你是只是记录以进行调试).您应该了解您正在使用的MOC.

此外,我建议使用父/子MOC进行此类处理,但如果操作正确,您正在做的事情应该有效.

父(私有并发类型)Main(主并发类型)

然后,使用您的背景MOC,让他们将主moc设置为其父级.当他们保存时,他们的对象被直接注入主MOC.然后,主MOC可以在以后发出保存以将它们放到磁盘上.

或者,您可以将背景MOC作为"父"的父级,然后"主"MOC可以重新发出获取以从父级获取数据.


归档时间:

查看次数:

9671 次

最近记录:

13 年,8 月 前