0

我遇到了使用NSFetchedResultsController的问题,我无法阻止它冻结用户界面。初始抓取很快发生,但是当我触发任何错误时,滚动表格视图时会导致冻结。我只使用测试8种元素和正在使用StackMob我的后端NSFetchedResultsController冻结UI

这里就是我宣布NSFetchedResultsController

- (NSFetchedResultsController *)fetchedResultsController { 

    if (_fetchedResultsController != nil) { 
     return _fetchedResultsController; 
    } 
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post" 
            inManagedObjectContext:_managedObjectContext]; 
    [fetchRequest setEntity:entity]; 


    NSSortDescriptor *sort = [[NSSortDescriptor alloc] 
          initWithKey:@"createddate" ascending:NO]; 
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; 

    NSFetchedResultsController *theFetchedResultsController = 
    [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
            managedObjectContext:_managedObjectContext 
             sectionNameKeyPath:nil 
               cacheName:nil]; 
    _fetchedResultsController = theFetchedResultsController; 

    return _fetchedResultsController; 
} 

这里是我的viewDidLoad:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    UIColor* backgroundImage = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:BACKGROUND_IMAGE_TAN]]; 
    [[self view] setBackgroundColor:backgroundImage]; 
    [[self tableView] setSeparatorStyle:UITableViewCellSeparatorStyleNone]; 
    _managedObjectContext = [[self.appDelegate coreDataStore] contextForCurrentThread]; 

    NSError *error;  
    if (![[self fetchedResultsController] performFetch:&error]) { 
     // Update to handle the error appropriately. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); // Fail 
    } 
} 

这里是我的cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"CCCell"; 
    CCCell *cell = (CCCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CCCell" owner:nil options:nil]; 
     cell = [topLevelObjects objectAtIndex:0]; 
     [cell setDelegate:self]; 
     [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
    } 

    Post* post = (Post*)[_fetchedResultsController objectAtIndexPath:indexPath]; 

    // 
    //IF I UNCOMMENT THIS LINE IT LOCKS THE UI 
    // 
    //NSLog(@"%@", [post valueForKey:@"price"]); 
    return cell; 
} 

如果我取消注释指定的行它会导致非常缓慢滚动

我试图围绕呼叫,像这样

dispatch_queue_t coreDataThread = dispatch_queue_create("com.YourApp.YourThreadName", DISPATCH_QUEUE_SERIAL); 

dispatch_async(coreDataThread, ^{ 
    Post* post = (Post*)[_fetchedResultsController objectAtIndexPath:indexPath]; 
    NSLog(@"%@", [post valueForKey:@"price"]); 
}); 

来电,但就要花很长的时间20秒左右

回答

1

设置您取一个fetchBatchSize请求的数量约等于表格在屏幕上的行数的两倍。这将节省不得不加载整个数据集。另请参阅NSFetchedResultsController关于cacheName的文档。顺便说一下,你的[[self.appDelegate coreDataStore] contextForCurrentThread]看起来很可疑。所有这些UI代码将在主线程上执行,因此要求另一个对象生成每个线程的MOC几乎肯定没有必要。

您的GCD代码不正确,因为您现在同时拥有主UI线程和您的GCD coreDataThread与同一NSFetchedResultsController进行对话,因此两个线程正在与同一个MOC进行对话。

如果你对Core Data性能感到困惑,那么值得开启SQL日志记录。

-com.apple.CoreData.SQLDebug 1 

作为命令行参数,通过Scheme Editor启用。