简体   繁体   English

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

[英]UITableView crashes on iOS 9 when endUpdates is called with EXC_BAD_ACCESS

After users upgraded to iOS 9, we've noticed a series of Bad Access ( EXC_BAD_ACCESS ) crashes that don't appear for users who are still on iOS 8. It happens when we call endUpdates on UITableView. 在用户升级到iOS 9后,我们注意到一系列错误访问( EXC_BAD_ACCESS )崩溃,这些崩溃对于仍在iOS 8上的用户来说不会出现。当我们在UITableView上调用endUpdates时会发生这种情况。

The crash logs include the following reasons: 崩溃日志包括以下原因:

Selector name found in current argument registers: numberOfRowsInSection: 在当前参数寄存器中找到的选择器名称:numberOfRowsInSection:

Selector name found in current argument registers: indexPathForRowAtGlobalRow: 在当前参数寄存器中找到的选择器名称:indexPathForRowAtGlobalRow:

Stack trace #1: 堆栈跟踪#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
[...]

Stack trace #2: 堆栈跟踪#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

We are able to repro the issue, but don't have any clue on how to go about fixing it. 我们能够重新解决这个问题,但是没有任何关于如何修复它的线索。

It looks like there's a bug in iOS9 when your UITableView has no rows that causes endUpdates to crash with EXC_BAD_ACCESS. 当您的UITableView没有导致endUpdates与EXC_BAD_ACCESS崩溃的行时,看起来iOS9中存在一个错误。 To work around this bug, you have to call tableView reloadData before calling beginUpdates. 要解决此错误,您必须在调用beginUpdates之前调用tableView reloadData。

From the thread that Claudio Redi directed me to: iOS9 iPad UITableView Crash (EXC_BAD_ACCESS) on 1st section insert , I've implemented the following workaround you add before calling [tableView beginUpdates]; Claudio Redi指导我的线程: iOS9 iPad UITableView Crash(EXC_BAD_ACCESS)在第1部分插入 ,我已经实现了在调用[tableView beginUpdates];之前添加的以下解决方法[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];
    }
}

I encountered this error when attempting to do more than one of the insert, delete, or reload operations between the beginUpdates() and endUpdates() calls, like so 尝试在beginUpdates()和endUpdates()调用之间执行多个插入,删除或重新加载操作时遇到此错误,如此

tableView.beginUpdates()
tableView.deleteRows(at: [deletePaths], with: .fade)
tableView.insertRows(at: [insertPaths], with: .fade)
tableView.endUpdates()

I was able to fix the issue by calling 我能够通过调用解决问题

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

instead of using the begin and end calls, ex. 而不是使用开始和结束调用,例如。

self.tableView.performBatchUpdates({
    self.tableView.deleteRows(at: [deletePaths], with: .fade)
    self.tableView.insertRows(at: [insertPaths], with: .fade)
}, completion: nil)

I faced this issue as well, the answer above of calling reloadData() on the table view did resolve the issue, however this was not ideal, as the animation associated with the update was not fluid, due to the reload. 我也面临这个问题,上面在表视图上调用reloadData()的答案确实解决了这个问题,但这并不理想,因为与更新相关的动画由于重新加载而不流畅。

The root of the issue is that I had programmatically called selectRow(at indexPath: IndexPath?, animated: Bool, scrollPosition: UITableView.ScrollPosition) on the table view, for an invalid index path at the time the method was called. 问题的根源是我在表视图上以编程方式调用了selectRow(at indexPath: IndexPath?, animated: Bool, scrollPosition: UITableView.ScrollPosition) ,用于调用方法时的无效索引路径。 (The updates in the table view were to expand/collapse a section to show the rows within or zero rows, I would at times select a row in a collapsed section). (表格视图中的更新是展开/折叠一个部分以显示行内或行中的行,我有时会在折叠部分中选择一行)。 This behaviour did not cause a crash when selecting a row for an index path that was not visible in the table view, however when updating the UITableView between beginUpdates( ) and endUpdates() calls after selecting an invalid index path, there would be a crash with EXC_BAD_ACCESS at the endUpdates() call. 在为表视图中看不到的索引路径选择行时,此行为不会导致崩溃,但是在选择无效索引路径后更新beginUpdates( )和endUpdates()之间的UITableView时,会发生崩溃在endUpdates()调用时使用EXC_BAD_ACCESS。 Adding a check before calling selectRowAt: to ensure the index path was visible/valid, before programmatically selecting resolved the crash without the need to call reloadData() 在调用selectRowAt:之前添加一个检查selectRowAt:以确保索引路径可见/有效,在编程选择解决崩溃之前无需调用reloadData()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM