[英]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
的多行选择的支持时,我使用了在didSelectRow
和didDeselectRow
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.selectRow
或tableView.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.