Ios 使用NSFetchedResultsController从数据库中提取会导致应用程序冻结
在我的应用程序中,在处理来自服务器的大数据时出现了冻结问题。我真的很困惑这个问题,最后我尝试了使用父子策略对coredata进行后台保存。在那之后,应用程序的速度比之前快了一点,但仍然存在小冻结。所以我认为现在的问题可能是因为获取核心数据。那么有没有办法在后台获取coredata呢? 我已经被搜索了链接 但这对我没有帮助Ios 使用NSFetchedResultsController从数据库中提取会导致应用程序冻结,ios,objective-c,core-data,Ios,Objective C,Core Data,在我的应用程序中,在处理来自服务器的大数据时出现了冻结问题。我真的很困惑这个问题,最后我尝试了使用父子策略对coredata进行后台保存。在那之后,应用程序的速度比之前快了一点,但仍然存在小冻结。所以我认为现在的问题可能是因为获取核心数据。那么有没有办法在后台获取coredata呢? 我已经被搜索了链接 但这对我没有帮助 -(NSFetchedResultsController*)fetchedResultsController { if (_fetchedResultsContr
-(NSFetchedResultsController*)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSString *loginUser=[[NSUserDefaults standardUserDefaults] valueForKey:@"currentUser"];
AppDelegate *sharedDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [sharedDelegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ThreadInfo"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"threadDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSPredicate *threadPredicate = [NSPredicate predicateWithFormat:@"userEmail == %@",loginUser];
// NSPredicate *providerPredicate = [NSPredicate predicateWithFormat:@"isReceiver == YES"];
// NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates: @[threadPredicate, providerPredicate]];
[fetchRequest setPredicate:threadPredicate];
[fetchRequest setFetchBatchSize:5];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:context sectionNameKeyPath:nil
cacheName:nil];
_fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
Appdelegate
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
// _managedObjectContext = [[NSManagedObjectContext alloc] init];
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"IXCoreDataModel" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Inxed.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
冻结时,我通过暂停应用程序在下面的行中发现了问题
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
ThreadInfo *info=[_fetchedResultsController objectAtIndexPath:indexPath];// THIS LINE TAKES TOO MUCH TIME
if([info.isSystemMessage boolValue]){
return 178+90+25;
} else {
return 300;
}
您正在处理大量数据,但一次获取所有数据,不要将数据量限制在有用的范围内。因此,在初始化NSFetchedResultsController
时,您可能不需要提取真实对象,使用错误,它们基本上是可以的
//FRC请求
NSFetchRequest*fetchRequest=[NSFetchRequest new];
fetchRequest.returnsObjectsAsFaults=是;//多余的,我只想说清楚
fetchRequest.fetchBatchSize=20;//甚至更少,这取决于用户可见的数据量
然后,如所示,使用估计高度
。这允许FRC猜测您要查看的数据的大致部分,当计算出实际高度时(如您所做的),数据就在手边
下一件事:索引数据。您的
isSystemMessage
是否已编制索引?应该是这样。怎么帮不了你?你做过任何分析来发现你的性能问题吗?用导致冻结的行更新了问题。请检查我已经检查了代码,但你知道我是新手,这让我更困惑。我想要的只是如何修改“fetchedResultsController”方法来处理后台抓取?不要再需要后台线程了。请看使用估计高度。