Ios NSFetchedResultsController-TableView中的UI更新不完整

Ios NSFetchedResultsController-TableView中的UI更新不完整,ios,uitableview,uikit,nsfetchedresultscontroller,Ios,Uitableview,Uikit,Nsfetchedresultscontroller,我正在使用NSFetchedResultsController刷新表视图的数据。数据本身是通过在后台运行的XML解析器提供的。解析器完成后,它将数据保存到自己的上下文中。NSFetchedResultsController立即拾取这些更改,并开始为每个更新的元素调用-(void)controller:didChangeObject:atIndexPath:forChangeType:newindexath:委托方法。这也很快,在日志文件中看起来完全正常 但是,在-(void)controller

我正在使用
NSFetchedResultsController
刷新表视图的数据。数据本身是通过在后台运行的XML解析器提供的。解析器完成后,它将数据保存到自己的上下文中。
NSFetchedResultsController
立即拾取这些更改,并开始为每个更新的元素调用
-(void)controller:didChangeObject:atIndexPath:forChangeType:newindexath:
委托方法。这也很快,在日志文件中看起来完全正常

但是,在
-(void)controllerDidChangeContent:
中,我调用
UITableView
-(void)endUpdates
。然后我在屏幕上看到更新动画,但在所有单元格中,除了最后一个只有一半可见外,唯一可见的是单元格左侧的图像。所有文本标签都不可见。大约需要5到10秒钟,然后所有标签都会弹出可见

但是,如果忽略
NSFetchedResultsController
的所有委托调用,只需在
-(void)controllerdChangeContent:
上调用
[self.tableView reloadData]
,一切都会正常工作。内容马上就到了

有人知道我做错了什么吗?分析器显示主线程基本上什么也不做。除了调度到表视图的事件外,触摸事件也得到了正确处理。这些没有处理。表视图似乎正忙于做一些严肃的工作,但我真的不知道这可能是什么,因为动画已经完成了

以下是我对NSFetchedResultsControllerDelegate的实现:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    UITableView* tableView = self.tableView;
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeUpdate:
    [(NewsItemCell*)[tableView cellForRowAtIndexPath:indexPath] updateWithNews:[self.fetchedResultsController objectAtIndexPath:indexPath]];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [self.tableView endUpdates];
}
-(void)controllerWillChangeContent:(NSFetchedResultsController*)控制器{
NSLog(@“%s”,函数);
[self.tableView开始更新];
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeSection:(id)sectionInfo atIndex:(nsInteger)ChangeType的sectionIndex:(NSFetchedResultsChangeType)类型{
NSLog(@“%s”,函数);
开关(类型){
案例NSFetchedResultsChangesInsert:
[self.tableView insertSections:[NSIndexSet IndexSetWithiIndex:sectionIndex]带RowAnimation:UITableViewRowAnimationAutomatic];
打破
案例NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet IndexetWithinIndex:sectionIndex]带RowAnimation:UITableViewRowAnimationAutomatic];
打破
}
}
-(void)控制器:(NSFetchedResultsController*)控制器didChangeObject:(id)索引路径中的一个对象:(NSIndexPath*)变更类型的indexPath:(NSFetchedResultsChangeType)类型newIndexPath:(NSIndexPath*)newIndexPath{
NSLog(@“%s”,函数);
UITableView*tableView=self.tableView;
开关(类型){
案例NSFetchedResultsChangesInsert:
[tableView InsertRowsAndExpaths:[NSArray arrayWithObject:newIndexPath]with RowAnimation:UITableViewRowAnimationAutomatic];
打破
案例NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
打破
案例NSFetchedResultsChangeUpdate:
[(NewsItemCell*)[tableView cellForRowAtIndexPath:indexPath]updateWithNews:[self.fetchedResultsController objectAtIndexPath:indexPath]];
打破
案例NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView InsertRowsAndExpaths:[NSArray arrayWithObject:newIndexPath]with RowAnimation:UITableViewRowAnimationAutomatic];
打破
}
}
-(void)controllerDidChangeContent:(NSFetchedResultsController*)控制器{
NSLog(@“%s”,函数);
[self.tableView endUpdates];
}
这是我手机布局的代码:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.fetchedResultsController.sections.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    id<NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController.sections objectAtIndex:section];
    return sectionInfo.numberOfObjects;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    News* model = [self.fetchedResultsController objectAtIndexPath:indexPath];

    NewsItemCell* cell = (NewsItemCell*)[tableView dequeueReusableCellWithIdentifier:NewsCellReuseIdentifier];
    [cell updateWithNews:model];
    cell.accessoryType = (model.content ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone);
    return cell;
}
-(NSInteger)节数表视图:(UITableView*)表视图{
返回self.fetchedResultsController.sections.count;
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节{
id sectionInfo=[self.fetchedResultsController.sections对象索引:section];
返回sectionInfo.numberOfObjects;
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
News*model=[self.fetchedResultsController对象索引路径:indexPath];
NewsItemCell*单元格=(NewsItemCell*)[tableView dequeueReusableCellWithIdentifier:NewsCellReuseIdentifier];
[单元更新:模型];
cell.accessoryType=(model.content?UITableViewCellAccessoryDisclosureIndicator:UITableViewCellAccessoryNone);
返回单元;
}
最基本的单元更新是:

- (void)updateWithNews:(News*)news {
    NSString* dateString = [[NSDateFormatter outputDateFormatter] stringFromDate:news.date];
    self.headlineLabel.text = (news.headline ? news.headline : NSLocalizedString(@"<NewsNoHeadlineReplacement>", nil));
    self.metaInfoLabel.text = [NSString stringWithFormat:NSLocalizedString(@"<NewsMetaInfoFormatDate>", nil), (dateString ? dateString : (NSLocalizedString(@"<NewsNoDateReplacement>", nil)))];

    self.readIndicatorView.hidden = (news.read != nil && [news.read compare:news.parsingDate] == NSOrderedDescending);
}
-(void)updateWithNews:(News*)News{
NSString*dateString=[[NSDateFormatter outputDateFormatter]stringFromDate:news.date];
self.headlineLabel.text=(news.headline?news.headline:NSLocalizedString(@“”,nil));
self.metaInfoLabel.text=[NSString stringWithFormat:NSLocalizedString(@“”,nil),(日期字符串?日期字符串:(NSLocalizedString(@“”,nil)))];
self.readIndicatorView.hidden=(news.read!=nil&&[news.read compare:news.parsingDate]==sensorderedescending);
}

占位符字符串也不会显示。标签完全是空的。只有图像可见

我首先要检查的事项:

  • 确保未在其他线程中执行提取
  • 确保抓取速度快,如果太慢也可能是原因

  • 您对NSFetchedResultsControllerDelegate的调用是否在后台线程中?这可能就是问题所在。要进行测试,您可以将bg moc的更改合并到主moc中,并观察主moc而不是bg moc。NSManagedObjectContext的一个实例只能由一个线程使用<
     case NSFetchedResultsChangeUpdate:
            [(NewsItemCell*)[tableView cellForRowAtIndexPath:indexPath] updateWithNews:[self.fetchedResultsController objectAtIndexPath:indexPath]];
            break;
    
    case NSFetchedResultsChangeUpdate:
            [tableView reloadRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic ];
            break;