当使用EXC_BAD_ACCESS调用endUpdates时,UITableView在iOS 9上崩溃

时间:2015-12-23 20:26:07

标签: ios uitableview ipad

用户升级到iOS 9后,我们注意到一系列不良访问(EXC_BAD_ACCESS)崩溃,这些崩溃对于仍在iOS 8上的用户来说不会出现。我们致电时会发生这种情况。 UITableView上的endUpdates

崩溃日志包括以下原因:

  

在当前参数寄存器中找到的选择器名称:   numberOfRowsInSection:

     

在当前参数寄存器中找到的选择器名称:   indexPathForRowAtGlobalRow:

堆栈跟踪#1:

1   UIKit   __46-[UITableView _updateWithItems:updateSupport:]_block_invoke + 92
2   UIKit   __46-[UITableView _updateWithItems:updateSupport:]_block_invoke1007 + 224
3   UIKit   -[UITableView _updateWithItems:updateSupport:] + 2556
4   UIKit   -[UITableView _endCellAnimationsWithContext:] + 12892
[...]

堆栈跟踪#2:

1   UIKit   __46-[UITableView _updateWithItems:updateSupport:]_block_invoke + 100
2   UIKit   -[UITableViewRowData globalRowForRowAtIndexPath:] + 102
3   UIKit   __46-[UITableView _updateWithItems:updateSupport:]_block_invoke1007 + 182
4   UIKit   -[UITableView _updateWithItems:updateSupport:] + 2300
5   UIKit   -[UITableView _endCellAnimationsWithContext:] + 10552

我们能够重新解决这个问题,但是没有任何关于如何修复它的线索。

3 个答案:

答案 0 :(得分:8)

当您的UITableView没有导致endUpdates与EXC_BAD_ACCESS崩溃的行时,看起来iOS9中存在一个错误。要解决此错误,您必须在调用beginUpdates之前调用tableView reloadData。

Claudio Redi指示我的帖子iOS9 iPad UITableView Crash (EXC_BAD_ACCESS) on 1st section insert,我已经实施了您在调用[tableView beginUpdates];之前添加的以下解决方法

if ([[NSProcessInfo processInfo] operatingSystemVersion].majorVersion >= 9)
{
    // there's a bug in iOS9 when your UITableView has no rows that causes endUpdates to crash with EXC_BAD_ACCESS
    // to work around this bug, you have to call tableView reloadData before calling beginUpdates.

    BOOL shouldReloadData = YES;
    NSInteger numberOfSections = [tableView.dataSource numberOfSectionsInTableView:tableView];
    for (NSInteger section = 0; section < numberOfSections; section++)
    {
        if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] > 0)
        {
            // found a row in current section, do not need to reload data
            shouldReloadData = NO;
            break;
        }
    }

    if (shouldReloadData) 
    {
        [tableView reloadData];
    }
}

答案 1 :(得分:1)

当我尝试在beginUpdates()和endUpdates()调用之间执行多个插入,删除或重载操作时,遇到了此错误,

AWS_STORAGE_BUCKET_NAME = env.str('AWS_STORAGE_BUCKET_NAME')
AWS_S3_CUSTOM_DOMAIN     = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME

我能够通过致电

解决此问题
tableView.beginUpdates()
tableView.deleteRows(at: [deletePaths], with: .fade)
tableView.insertRows(at: [insertPaths], with: .fade)
tableView.endUpdates()

例如,而不是使用开始和结束调用。

performBatchUpdates(_ updates: (() -> Void)?, completion: ((Bool) -> Void)? = nil)

答案 2 :(得分:0)

我也遇到了这个问题,上面在表视图上调用reloadData()的答案确实解决了这个问题,但这并不理想,因为与更新相关联的动画由于重新加载而不稳定

问题的根源是我在表视图上以编程方式调用了selectRow(at indexPath: IndexPath?, animated: Bool, scrollPosition: UITableView.ScrollPosition),因为在调用该方法时索引路径无效。 (表视图中的更新是展开/折叠部分以显示其中的行或零行,我有时会在折叠部分中选择一行)。当为表视图中不可见的索引路径选择一行时,但在选择了一个UITableViewbeginUpdates(之间的endUpdates()调用之后,此行为不会导致崩溃索引路径无效,则endUpdates()调用时EXC_BAD_ACCESS会崩溃。在调用selectRowAt:之前添加检查以确保索引路径可见/有效,然后以编程方式选择解决了崩溃,而无需调用reloadData()