[英]When to call tableView.selectRow to avoid UITableViewAlertForCellForRowAtIndexPathAccessDuringUpdate
在实现对UITableView
的多行选择的支持时,我使用了在didSelectRow
和didDeselectRow
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.selectRow
或tableView.deselectRow
,而是从viewDidLoad
调用它来获取视图 controller。 或者可能在设置rowSelectionState
的值之后,如果在加载视图 controller 之后发生这种情况。
问题是当您尝试更改选择 state 时,您处于UITableView
委托方法中,因此它无法正常工作。
另请注意,您可以检查 UITableView 上的indexPathsForSelectedRows
属性,这样当您对UITableView
进行更改rowSelectionState
,您可以只更新那些需要它的行的选择 state。 但同样,当您处于UITableView
委托方法的中间时,不要这样做。
此外,从它的外观来看,您正在尝试使用rowSelectionState
来跟踪哪些已经在选定的 state 中,因此您可能只需要引用indexPathsForSelectedRows
属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.