NSFetchedResultsController不显示在不同的上下文更新(NSFetchedRe

2019-06-24 04:05发布

我有一个NSFetchedResultsController和一些操作更新通过管理在单独的线程对象NSOperationQueue

财务汇报局(其谓语)看起来是这样的:

- (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;
}

主线程和线程操作有自己的管理对象上下文。 他们只共享相同的协调员。

内螺纹操作我的改变isSync属性从NOYES 。 要知道什么是Check实体更新,主要的背景下传递给螺纹一个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;
}

当线程操作调用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];
}

日志记录的说明notification导致验证更改正确执行。

我的问题

的代表方法NSFetchedResultsControllerDelegate不叫。

这是因为处理相同的上下文很奇怪,主要的一个,允许监听变化和委托方法被调用,例如删除的行对象UITableView

我发现在SO一些议题同样的问题。 我已经尝试了所有的解决方法,但我不能找到一个有价值的解决方案:

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

  2. 从后台线程合并更新后NSFetchedResultsController不点火的委托方法

  3. NSFetchedResultsController谓语忽略的变化,从不同的NSManagedObjectContext合并

先感谢您。

编辑

上面的代码是在以前的模式工作。 然后,我创建了从以前的一个新模式的复制(粘贴)的实体,现在它不工作了。

建议?

编辑2

这是我使用的谓词NSFetchedResultsController吸气。 这是我的错,但是当我写的文章中,我并没有把它复制。

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

// previous code here
[fetchRequest setSortDescriptors:sortDescriptors];

现在,关于乔迪最后的评论

在你的NSOperation的主要(),您正在加载新的对象,并在那里,它看起来像你的每一个新的对象设置isSync为YES。 您使用的fetchedResultsController谓词正在查找仅对具有isSync ==没有对象。

我希望,当属性isSync设置为YES时, NSFetchedResultsController指出,修改和删除,并非谓词匹配的行。 我错了吗?

请记住,合并从背景到主线程发生变化时,我能看到几个对象都更新了isSync财产。

Answer 1:

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

仔细检查您是否正确注册接收从背景MOC通知。

注册的所有对象收到的所有通知。 在该方法中,记录事件,它的所有数据。 当对象是一个MOC,转储其所有特性(特别是注册,插入,更新和删除的对象的列表)。

权利之前将一个日志语句后保存调用,并在合并通知的通知处理程序。

此外,您省去大量的代码,所以很难知道你实际上是在做什么,但代码示例包括你看起来是isSync硬盘设置为YES所有对象被加载,但你的读取请求只希望那些isSync集为NO。 这些新的对象都不会传递谓词。

最后,仔细检查你的模型定义,并确保您使用的是正确的号码类型。 这可能是问题的一大来源。

编辑

噢,我忘了...你取请求没有一种描述。 当你创建一个FRC,你取的请求必须至少包含一个排序描述符...如果你有多个部分,第一个排序描述符用于组的对象为几个部分。

为了跟进Alexsander的评论......我提到它在我的文章的开头,但你肯定不希望从MOC听通知,除非它是知名的作为你们的一个(当然,除非,你是只是记录用于调试目的)。 你应该知道你正在使用的MOC。

此外,我会建议使用父/子MOCS对于这种类型的处理,但如果处理得当你正在做什么应该工作。

家长(私人并发型)主(主并发型)

然后,你的背景MOCS,只是让他们设置主MOC作为他们的父母。 当他们保存,他们的对象得到直接注入主MOC。 主要MOC然后可以发出保存在稍后时间把它们放到磁盘上。

或者,您可以家长,你的背景建设部“父”,然后在“主” MOC只需重新发出取从父获取数据。



Answer 2:

我有同样的问题,我与父/子上下文来解决。 这里是我的问题。

我正在更新在后台线程有它自己的我的核心数据对象图managedObjectContext (这是必须的),和我的fetchedResultsController无法拿起做数据库的变化。

我解决了它后,我花了一些注意事项:

ManagedObjectContext s的不是线程安全的,这意味着一个managedObjectContext不能与其他线程共享。 如果一个线程需要使用managedObjectContext ,那么它将初始化自己的managedObjectContext。

要初始化managedObjectContext有两种方式:

  • alloc/init然后将其persistentStoreCoordinator属性

  • alloc/init然后设置一个parentContext属性而不是persistentStoreCoordinator属性

注意:一个人不能同时设置persistentStoreCoordinatorparentContext一个财产managedObjectContext

使用父/子上下文是当一个上下文被上被“链接到控制器和只需要在主线程所使用的UI对象”(核心数据文档)后台线程运行所需的。

以下是需要的父/子上下文的要求:

  • 父上下文住在主线程

  • 孩子上下文住在后台线程

  • 两种情况下需要与初始化initWithConcurrencyType:NSMainQueueConcurrencyType方法。

  • 当改变的批次已在儿童方面已经完成,两种情况下需要执行保存操作。 这些保存操作需要被嵌套在performBlock方法,即:

     childContext performBlock:^{ [childContext save:nil]; [self.parentContext performBlock:^{ [self.parentContext save:nil]; }]; }]; 

编辑:上面的代码实际上是有两个原因一个坏主意:

1)它的工作原理,但不保存父上下文。

2)如果父上下文上运行的主线程被阻塞。

我希望它帮助!

编辑:这是一个计算器线程这让我大大: 请问核心数据父ManagedObjectContext需要分享与孩子上下文中的并发性类型?



文章来源: NSFetchedResultsController doesn't show updates from a different context