簡體   English   中英

當使用EXC_BAD_ACCESS調用endUpdates時,UITableView在iOS 9上崩潰

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

在用戶升級到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

我們能夠重新解決這個問題,但是沒有任何關於如何修復它的線索。

當您的UITableView沒有導致endUpdates與EXC_BAD_ACCESS崩潰的行時,看起來iOS9中存在一個錯誤。 要解決此錯誤,您必須在調用beginUpdates之前調用tableView reloadData。

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];
    }
}

嘗試在beginUpdates()和endUpdates()調用之間執行多個插入,刪除或重新加載操作時遇到此錯誤,如此

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

我能夠通過調用解決問題

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

而不是使用開始和結束調用,例如。

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

我也面臨這個問題,上面在表視圖上調用reloadData()的答案確實解決了這個問題,但這並不理想,因為與更新相關的動畫由於重新加載而不流暢。

問題的根源是我在表視圖上以編程方式調用了selectRow(at indexPath: IndexPath?, animated: Bool, scrollPosition: UITableView.ScrollPosition) ,用於調用方法時的無效索引路徑。 (表格視圖中的更新是展開/折疊一個部分以顯示行內或行中的行,我有時會在折疊部分中選擇一行)。 在為表視圖中看不到的索引路徑選擇行時,此行為不會導致崩潰,但是在選擇無效索引路徑后更新beginUpdates( )和endUpdates()之間的UITableView時,會發生崩潰在endUpdates()調用時使用EXC_BAD_ACCESS。 在調用selectRowAt:之前添加一個檢查selectRowAt:以確保索引路徑可見/有效,在編程選擇解決崩潰之前無需調用reloadData()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM