多线程核心数据导致UI挂起

Nat*_*kin 0 multithreading core-data ios

我正在尝试在我的应用程序的后台对相当大的数据集(~60000行)执行获取.尽管使用了单独的线程,但每当执行获取时,UI都会显着挂起一秒钟.我的方法是否正确?

- (id)init
{
    if(self = [super init])
    {
        ABAppDelegate *appDelegate = (ABAppDelegate *)[[UIApplication sharedApplication] delegate];
        _rootManagedObjectContext = appDelegate.managedObjectContext;

        _backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_backgroundContext setPersistentStoreCoordinator:_rootManagedObjectContext.persistentStoreCoordinator];
    }
    return self;
}


- (void)fetch {
    [_backgroundContext performBlock:^{
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ItemPhoto"];
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"full_uploaded_to_server == 0 OR thumb_uploaded_to_server == 0"];
        fetchRequest.predicate = pred;
        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"modified" ascending:YES]; //Start at the back of the queue
        fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
        fetchRequest.fetchBatchSize = 1;
        fetchRequest.fetchLimit = 1;

        NSError *error;
        NSArray *photos = [_backgroundContext executeFetchRequest:fetchRequest error:&error];
        if(error != nil) {
            NSLog(@"Fetch error: %@", error.localizedDescription);
        }
    }];
}
Run Code Online (Sandbox Code Playgroud)

看看乐器,这绝对是需要executeFetchRequest:很长时间才能完成的调用,它似乎确实在自己的线程上运行.为什么这会导致UI挂起?

谢谢!

Mar*_*rra 5

任何针对该活动的活动NSPersistentStoreCoordinator都会导致一系列其他活动.如果你在一个线程上获取而另一个线程试图访问NSPersistentStoreCoordinator它,那么它将被阻止.

这可以通过以下两种方式之一解决:

  1. 减少提取以使块不明显.例如,获取块可以帮助减少此问题.
  2. 确保UI正在公开的数据已完全加载到内存中.这将阻止主线程尝试命中NSPersistentStoreCoordinator并被阻止.

根据应用程序和情况,这些实现中的一个或另一个(或两者)将消除该问题.

在一天结束时,后台线程不是解决获取时间的银弹.如果你打算在后台线程上获取只是为了将它们放到主线程上,你会对性能感到失望.

如果您在后台线程上获取非UI用途,请考虑减小每次获取的大小或更改批量大小等,以减少获取时间本身.

更新

预热缓存在iOS上不像以前那样在OS X上运行.您可以通过配置NSFetchRequest对象来完全加载对象,以便完全加载对象,加载关系(如果需要),批量大小和获取大小足够大.当然,这需要与内存使用量进行平衡.