NSFetchedResults控制器在不同的视图控制器互相更新?

好吧,我越来越一般这个问题,因为我已经注意到我的应用程序由于这个几个滞后。 我已经注意到重新sorting的问题,但也发生在其他地方。 我有一个CoreDataViewController类,所有我的表视图控制器的子类。 在这个类中,我基本上拥有所有的NSFetchedResultsController委托方法,就像它们在苹果文档中一样。

然后我试着找出这个NSFetchedResultsController发现变化的频率,以找出我的时间滞后的地方:

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { if(self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return; NSLog(@"ControllerDidChangeContent"); TICK; [self.tableView endUpdates]; TOCK; } 

所以例如在我的视图控制器A中,我有这个获取请求(从viewDidLoad调用):

 - (void)setupFetchedResultsController { //NSError *error = nil; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SpendingCategory"]; request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]]; //[self.mainCategory.managedObjectContext executeFetchRequest:request error:&error]; request.predicate = [NSPredicate predicateWithFormat:@"belongsToMainCategory = %@", self.mainCategory]; self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:self.mainCategory.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; } 

如果我在此视图控制器中更改我的对象的属性,则我的日志只会打印出“ControllerDidChangeContent”注释。 和预期一样快。 我的意思是,只是一个简单的属性更改,只是改变一些数字或string等,如:

 spendingCategory.name = @"Hello world"; 

但是,如果我已经访问另一个视图控制器,并在viewDidLoad中设置其NSFetchedResultsController,我的日志打印出来两次。 这里是第二个NSFetchedResultsController:

 - (void)setupFetchedResultsController { self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"SpendingCategory"]; NSSortDescriptor *mainCatPosition = [[NSSortDescriptor alloc] initWithKey:@"belongsToMainCategory.position" ascending:YES]; NSSortDescriptor *spendingCatPosition = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES]; request.sortDescriptors = [NSArray arrayWithObjects:mainCatPosition,spendingCatPosition,nil]; request.predicate = [NSPredicate predicateWithFormat:@"liveBudget = %@", [NSNumber numberWithBool:YES]]; self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"belongsToMainCategory.position" cacheName:@"LiveBudget"]; } 

我前面提到的简单的属性改变就更长了。 这是因为现在我的日志打印出两次(!)ControllerDidChangeContent。 第一个TICK-TOCK仍然和以前一样快,但第二个则超过了一秒。 我想这是因为我有两个NSFetchedResultsController看着同一个实体。

  1. 问题:我还不太明白为什么他们互相影响? 我的意思是确定我更新一个视图控制器中的属性,所以另一个当然应该注意到这个变化,但为什么两个didChangeContent触发?

  2. 问题:我怎样才能避免呢? 或者我该如何改进?

我认为最好是在转向这个解决scheme之前检查1秒的停顿。
我自己,我没有经历过在同一个环境下使用多个FRC的延迟,所以我的猜测是在其他地方的问题。

至于你的问题:

  1. FRC正在侦听“NSManagedObjectContextObjectsDid 更改通知”,因此所有在相同对象上侦听同一上下文的FRC将在这些对象更改时触发其委托方法。 因此,很明显为什么你的日志打印了两次(2个不同的FRC改变了他们的内容)

  2. 1 [sec]是堵塞主线程的一个长时间,应该解决(用仪器检查可以做什么)。 正如我所提到的,当在相同的上下文中使用FRC时,没有办法避免这种情况,但是您可以为每个VC创build一个子上下文,使FRC仅监听该子上下文,然后更改将仅对其他FRC当你保存上下文链。 只要你的VC堆栈不是很深,这应该不是一个真正的问题。 在任何情况下,您都希望其他VC在更新tableview时更新更新,以便提供stream畅的用户体验,所以如果更新花费太长时间,您应该明白原因。