簡體   English   中英

何時調用 tableView.selectRow 以避免 UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate

[英]When to call tableView.selectRow to avoid UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate

在實現對UITableView的多行選擇的支持時,我使用了在didSelectRowdidDeselectRow rowSelectionState rowSelectionState 的當前rowSelectionState然后用於通過調用configureCellSelectionState() cellForRowAt來控制向用戶顯示正確選擇的行。 從技術上講,從 iOS 14.4 開始,這是應該做的,但需要注意的是 iOS 在 Z146184A444F3817CC13AEZ52 中轉儲了一堆UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate警告。

    private var rowSelectionState = [IndexPath: Bool]()

    func configureCellSelectionState(_ indexPath: IndexPath) {
        guard tableView.isEditing else { return }
        if rowSelectionState[indexPath] ?? false {
            tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
        } else {
            tableView.deselectRow(at: indexPath, animated: false)
        }
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if tableView.isEditing {
            rowSelectionState[indexPath] = true
        }
    }
    
    override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        if tableView.isEditing {
            rowSelectionState[indexPath] = false
        }
    }

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        
        if !editing {
            rowSelectionState.removeAll()
        }
    }

cellForRowAt內部調用configureCellSelectionState()是最初的編寫方式。

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: rowCellId, for: indexPath)
        configureCellSelectionState(indexPath)
        return cell
    }

在仔細注意 stream 警告后,一些搜索 StackOverflow 導致我在willDisplay而不是cellForRowAt內部調用configureCellSelectionState() 不幸的是,警告仍然存在。

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        configureCellSelectionState(indexPath)
    }

示例警告:

2021-02-09 09:12:14.119983-0500 XXX [55266:1705708] [Assert] 
Attempted to call -cellForRowAtIndexPath: on the table view while it was in the process of updating its visible cells, which is not allowed. 
Make a symbolic breakpoint at UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate to catch this in the debugger and see what caused this to occur. 
Perhaps you are trying to ask the table view for a cell from inside a table view callback about a specific row? 
Table view: <UITableView: 0x7b7800045c00; frame = (0 0; 390 844); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7b0c000fee50>; layer = <CALayer: 0x7b08002be520>; contentOffset: {0, -143}; contentSize: {390, 264}; adjustedContentInset: {143, 0, 143, 0}; dataSource: <XXX.YYYTableViewController: 0x7b640006b800>>

所以問題是,在避免UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate警告的同時實現這種功能的“正確”方法是什么?

在顯示單元格時不要調用tableView.selectRowtableView.deselectRow ,而是從viewDidLoad調用它來獲取視圖 controller。 或者可能在設置rowSelectionState的值之后,如果在加載視圖 controller 之后發生這種情況。

問題是當您嘗試更改選擇 state 時,您處於UITableView委托方法中,因此它無法正常工作。

另請注意,您可以檢查 UITableView 上的indexPathsForSelectedRows屬性,這樣當您對UITableView進行更改rowSelectionState ,您可以只更新那些需要它的行的選擇 state。 但同樣,當您處於UITableView委托方法的中間時,不要這樣做。

此外,從它的外觀來看,您正在嘗試使用rowSelectionState來跟蹤哪些已經在選定的 state 中,因此您可能只需要引用indexPathsForSelectedRows屬性。

暫無
暫無

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

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