好的,我对这个问题越来越普遍了,因为我已经注意到我的应用程序中有几个滞后因此。我已经注意到重新排序的问题,但它也发生在其他地方。我有一个CoreDataViewController类,我的所有表视图控制器都是子类。在这个类中,我基本上拥有所有NSFetchedResultsController委托方法,因为它们在apple docs中。
然后我试图找出这个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”注释一次。并且和预期的一样快。我的意思是真的只是一个简单的属性改变,只是改变一些数字或字符串等,如:
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仍然和以前一样快,但第二个TICK-TOCK需要一秒钟。我想这是因为我有两个NSFetchedResultsController观看同一个实体。
问题: 我还是不太明白为什么他们互相影响?我的意思是确定我在一个视图控制器中更新一个属性,所以另一个当然应该注意到这个变化,但为什么会触发两个didChangeContent?
问题: 我怎么能避免这种情况?或者我该如何改进?
答案 0 :(得分:0)
我认为在转向此解决方案之前,最好先检查1 [秒]暂停的原因 在同一个环境中使用多个FRC时,我没有经历过这种延迟,所以我的猜测是其他地方的问题。
关于你的问题:
FRC正在侦听“NSManagedObjectContextObjectsDid 更改通知”,因此当更改这些对象时,所有FRC在相同对象上侦听相同上下文将触发其委托的方法。因此,很明显为什么你的日志打印两次(2个不同的FRC改变了他们的内容)
1 [sec]是阻塞主线程的很长时间,应该解决(用仪器检查可以做什么)。正如我所提到的,当在相同的上下文中使用FRC时,没有办法避免这种情况,但你可以为每个VC创建一个子上下文,使得FRC只监听那个子上下文,然后只有其他人可以看到更改。保存上下文链时的FRC。只要你的VC堆栈不是很深,这应该不是一个真正的问题。在任何情况下,您希望其他VC在更新tableview时更新更新以提供流畅的用户体验,因此如果更新花费的时间太长,您应该明白为什么。