简体   繁体   English

何时调用 tableView.selectRow 以避免 UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate

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

In implementing support for multiple selection of rows of a UITableView , I'm using a private variable rowSelectionState which is managed during didSelectRow and didDeselectRow .在实现对UITableView的多行选择的支持时,我使用了在didSelectRowdidDeselectRow rowSelectionState The current state of rowSelectionState is then used to control display of the properly selected rows to the user via calls to configureCellSelectionState() cellForRowAt . rowSelectionState 的当前rowSelectionState然后用于通过调用configureCellSelectionState() cellForRowAt来控制向用户显示正确选择的行。 Technically as of iOS 14.4, this does what it is supposed to do, with the caveat that iOS dumps a bunch of UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate warnings in XCode.从技术上讲,从 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()
        }
    }

Calling configureCellSelectionState() inside of cellForRowAt is how this was originally written.cellForRowAt内部调用configureCellSelectionState()是最初的编写方式。

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

After taking closer notice of the stream of warnings, some searching StackOverflow led me to call configureCellSelectionState() inside of willDisplay rather than cellForRowAt .在仔细注意 stream 警告后,一些搜索 StackOverflow 导致我在willDisplay而不是cellForRowAt内部调用configureCellSelectionState() Unfortunately, the warnings are still there.不幸的是,警告仍然存在。

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

Example warning:示例警告:

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>>

So the question is, what is the "proper" way to implement this kind of feature while avoiding the UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate warning?所以问题是,在避免UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate警告的同时实现这种功能的“正确”方法是什么?

Instead of calling tableView.selectRow or tableView.deselectRow while displaying the cell, call it instead from viewDidLoad for your view controller.在显示单元格时不要调用tableView.selectRowtableView.deselectRow ,而是从viewDidLoad调用它来获取视图 controller。 Or perhaps after setting the value of rowSelectionState , if that happens after loading the view controller already.或者可能在设置rowSelectionState的值之后,如果在加载视图 controller 之后发生这种情况。

The issue is that you're inside a UITableView delegate method when you're trying to change the selection state, so it's not going to work properly.问题是当您尝试更改选择 state 时,您处于UITableView委托方法中,因此它无法正常工作。

Note also that you can check the indexPathsForSelectedRows property on UITableView so that when you do make changes to rowSelectionState , you can just update the selection state of only those rows that need it.另请注意,您可以检查 UITableView 上的indexPathsForSelectedRows属性,这样当您对UITableView进行更改rowSelectionState ,您可以只更新那些需要它的行的选择 state。 But again, do this not when you're in the middle of a UITableView delegate method.但同样,当您处于UITableView委托方法的中间时,不要这样做。

Also, from the looks of it, you're trying to use rowSelectionState to track which ones are already in a selected state, so maybe you need to just reference the indexPathsForSelectedRows property.此外,从它的外观来看,您正在尝试使用rowSelectionState来跟踪哪些已经在选定的 state 中,因此您可能只需要引用indexPathsForSelectedRows属性。

暂无
暂无

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

相关问题 Swift - 在 tableView.selectRow 中更改背景颜色 - Swift - Change background color in tableView.selectRow 当我使用 UIAdaptivePresentationControllerDelegate (Swift 5) 时,tableView.selectRow(...) 不起作用 - tableView.selectRow(...) doesn't work when I use UIAdaptivePresentationControllerDelegate (Swift 5) 方法selectRow(at:animated:scrollPosition :)不调用tableView(_:didSelectRowAt :) - The method selectRow(at:animated:scrollPosition:) doesn't call tableView(_:didSelectRowAt:) 何时在刚刚加载的UIPickerView上调用selectRow :? - When to call selectRow: on a UIPickerView that has just loaded? 如何修复:当我在搜索栏中单击“取消”时,TableView 中的 func selectRow 不起作用 - How to fix: func selectRow in the TableView does not work when I click Cancel in search bar tableviewcell 的 isSelected 方法和 tableview 的 selectRow(at:animated:scrollPosition:) 有什么区别 - what is the different between isSelected method of tableviewcell and selectRow(at:animated:scrollPosition:) of tableview 单击表格视图单元格时调用 - Call when clicked on tableview cell 在 UIPickerView 上设置 selectRow() 时出现越界异常 - Beyond bounds exception when setting selectRow() on UIPickerView 如何强制UIPickerView.selectRow调用didSelectRow方法? - How to force UIPickerView.selectRow call didSelectRow method? 如何避免UITableViewCell在TableView滚动时重复添加自定义标签? - How to avoid UITableViewCell repeat add custom label when TableView scrolling?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM