首页 > 解决方案 > UITableViewAlertForLayoutOutsideViewHierarchy当UITableView没有窗口iOS13

问题描述

我开始在 iOS13 上收到警告(下)。我注意到弹出此警告是因为UITableView' 的窗口为空(选择了另一个选项卡,在表选择上推送了详细视图控制器......)。我正在尝试UITableViewNSFetchedResultController代表更新。在 iO13 上执行此操作以保持表格更新的正确方法是什么?

下面的代码在以前的版本中运行良好。

PS:任何类型的beginUpdates, reloadRowsAtIndexPaths:withRowAnimation:, insertSections:withRowAnimation:, endUpdates都会引起这个警告。

PS:我尝试重新加载表,但如果我向后导航,我会失去动画以取消选择行(清除行选择)。

2019-09-27 09:40:42.849128+0200 xxx[63595:9762090] [TableView] 仅警告一次:UITableView 被告知在视图层次结构中布局其可见单元格和其他内容(表格视图或其之一superviews 尚未添加到窗口中)。这可能会在没有准确信息的情况下强制表视图内的视图加载和执行布局(例如表视图边界、特征集合、布局边距、安全区域插入等),从而导致错误,并且还会由于额外的布局传递而导致不必要的性能开销. 在 UITableViewAlertForLayoutOutsideViewHierarchy 处创建一个符号断点,以便在调试器中捕获此问题并查看导致此问题发生的原因,因此如果可能,您可以完全避免此操作,或者将其推迟到表格视图添加到窗口中。表视图:; 层 = ; 内容偏移:{0,-64}; 内容大小:{375, 3432};调整内容插入:{64, 0, 0, 0}; 数据来源:>

// ------------  ------------  ------------  ------------  ------------  ------------
#pragma mark - FetchedResultsController delegate

- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller {
//    if (self.tableView.window) {
        [self.tableView beginUpdates];
//    }
}
- (void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    if (type == NSFetchedResultsChangeInsert && newIndexPath != nil) {
        [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }

    if (type == NSFetchedResultsChangeUpdate && indexPath != nil) {
        [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
//        id<CellLoadable> cell = [self.tableView cellForRowAtIndexPath:indexPath];
//        [cell loadData:anObject];
    }

    if (type == NSFetchedResultsChangeMove && indexPath != nil && newIndexPath != nil) {
        // if cell is visible, update it
        id<CellLoadable> cell = [self.tableView cellForRowAtIndexPath:indexPath];
        [cell loadData:anObject];
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
    }
}

- (void) controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    if (type == NSFetchedResultsChangeInsert) {
        [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
    }
    if (type == NSFetchedResultsChangeDelete) {
        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
    }
}

- (void) controllerDidChangeContent:(NSFetchedResultsController *)controller {
//    if (self.tableView.window) {
        [self.tableView endUpdates];
//    }
}

标签: iosuitableviewnsfetchedresultscontrollerios13

解决方案


PS:任何一种 beginUpdates 、 reloadRowsAtIndexPaths:withRowAnimation: 、 insertSections:withRowAnimation: 、 endUpdates 都会导致这个警告。

我发现将表更新包装在 dispatch_async 中触发断点的位置可以消除问题:

dispatch_async(dispatch_get_main_queue(), ^(void){
    [self.table reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];
});

(可能必须在调用堆栈中断时找到调用)


推荐阅读