我正在尝试在我的应用程序的后台对相当大的数据集(~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);
}
}];
}
查看乐器,这肯定是对executeFetchRequest:
的调用需要很长时间才能完成,而且似乎确实在自己的线程上运行。为什么会导致UI挂起?
谢谢!
答案 0 :(得分:5)
针对NSPersistentStoreCoordinator
的任何活动都会导致一系列针对它的活动。如果您在一个线程上获取而另一个线程试图访问NSPersistentStoreCoordinator
,则它将被阻止。
这可以通过以下两种方式之一解决:
NSPersistentStoreCoordinator
并被阻止。根据应用程序和情况,这些实现中的一个或另一个(或两者)将消除此问题。
在一天结束时,后台线程不是解决获取时间的银弹。如果你打算在后台线程上获取只是为了将它们放到主线程上,你会对性能感到失望。
如果您要在后台线程上获取非UI用途,请考虑减小每次获取的大小或更改批量大小等,以减少获取时间本身。
预热缓存并不像在OS X上那样在iOS上工作。您可以通过配置NSFetchRequest
将对象完全加载到内存中,以便对象完全加载,关系是加载(如果需要),您的批量大小和获取大小足够大。当然,这需要与内存使用相平衡。