使用NSFetchedResultsController从数据库中获取会导致应用程序冻结

时间:2015-04-09 12:19:33

标签: ios objective-c core-data

在我的应用程序中,从服务器处理大数据时出现了冻结问题。我真的很困惑这个问题,At Last我尝试使用Parent-Child策略保存coredata。之后,应用程序变得比之前更快,但仍然存在小的冻结。所以我想现在问题可能是因为获取核心数据。那么有没有办法在后台获取coredata? 我已经搜索了链接 NSFetchedResultsController: Fetch in a background thread

但这些链接对我没有帮助。

   -(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;
 }

1 个答案:

答案 0 :(得分:0)

您正在处理大数据但是一次获取所有数据并且不会将其限制为有用的数量。因此,在初始化NSFetchedResultsController时,您可能不需要获取真实对象,使用错误,它们大多数都可以。

// FRC request NSFetchRequest *fetchRequest = [NSFetchRequest new]; fetchRequest.returnsObjectsAsFaults = YES;// redundant, I only want to make this clear fetchRequest.fetchBatchSize = 20; // or even less, depending on your amount of data visible to the user

然后,作为Wain said,使用estimated height。这允许FRC猜测要查看的数据的粗略部分以及何时计算实际高度(如您所做的那样)数据即将到来。

下一步:索引数据。您的isSystemMessage已编入索引吗?应该是。