gpt4 book ai didi

swift ,UIKit : How can I diagnose EXC_BAD_INSTRUCTION in UIKit on tableView. PerformBatchUpdates()

转载 作者:行者123 更新时间:2023-11-30 10:31:41 30 4
gpt4 key购买 nike

我多年来一直在与 tableView.performBatchUpdates 的 UIKit 问题作斗争。

我有一个简单的数据模型,其中包含由 tableView 和 tableViewCells 驱动的 15 个项目,其中包含 15 个相应的单元格(带回收),其中一个是自定义复选框控件。当单击复选框“打开”时,这 15 个元素中的 7 个将被删除并添加(在中间),然后再次单击“关闭”,重新添加相同的 7 个单元格(在中间)。前 5 个不动。最后 3 个放置在删除/添加的中间 7 个元素之后。

我诊断了数据源和 TableView 的所有更新。首先适当更新数据源,然后在tableView上适当调用deleteRows、insertRows和moveRow。

无需滚动 tableView(同时滚动到 ON 和 OFF 状态)即可正常工作,从而导致我的 7 行通过幻灯片 IN/OUT 动画显示和隐藏。我可以重复多次,并且直到我不将单元格滚动到 View 之外之前它都不会崩溃。

现在,如果我将 tableView 一直向上拖动,直到大多数单元格都被 cellForRow 调用(回收并重新填充),然后使用该复选框,那么我就会在 tableView 上遇到 EXC_BAD_INSTRUCTION 崩溃。 PerformBatchUpdates() 方法(与我的任何代码无关,堆栈跟踪仅在 PerformBatchUpdates() 处结束)。我对此错误做了很多研究,通常它是 NIL 的强制展开,如下所示:Diagnosing EXC_BAD_INSTRUCTION in Swift standard library

问题是:我的单元非常复杂,需要进行大量验证和配置,并且堆栈跟踪不会导致我的任何代码。我还验证了工作状态(首先不滚动到 View 之外)与非工作状态(首先滚动到 View 之外)与performBatchUpdates() 中的deleteRows、addRows 和moveRow 的逻辑没有区别。因此,后续对 cellForRow() 的调用会对单元格执行一些操作,导致 UIKit 对其内容不满意。由于第一次一切正常,它一定与细胞的回收有关,也许还与陈旧的数据有关。

有没有办法可以将 UIKit 源附加到我的项目中,以便我可以看到它正在获取 EXC_BAD_INSTRUCTION?

是否有任何其他符号调试技巧可以用来更好地理解哪些对象与 EXC_BAD_INSTRUCTION 相关?如果我从头开始制作一个示例项目,它可能会正常工作,因此它特定于我的实际单元结构和事件逻辑,这会扰乱 UIKit。

目前,我被迫不使用 tableView 动画(performBatchUpdates()),而只是执行 tableView.reloadData(),直到我弄清楚这一点。

用异常断点捕获异常时的图像:(堆栈跟踪仅上升到performBatchUpdates()本身,在UIKit中,其中或之上没有任何内容)。所以 UIKit 是个异常(exception)。

enter image description here

enter image description here

enter image description here

以下是正在发生的所有删除/移动/添加操作的日志:

Hide Fields: 
FORM DELETING: 0, 5
FORM DELETING: 0, 6
FORM DELETING: 0, 7
FORM DELETING: 0, 8
FORM DELETING: 0, 9
FORM DELETING: 0, 10
FORM DELETING: 0, 11
FORM MOVING: [0, 12], to: [0, 5]
FORM MOVING: [0, 14], to: [0, 7]
FORM MOVING: [0, 13], to: [0, 6]

Show Fields:
FORM ADDING: 0, 5
FORM ADDING: 0, 6
FORM ADDING: 0, 7
FORM ADDING: 0, 8
FORM ADDING: 0, 9
FORM ADDING: 0, 10
FORM ADDING: 0, 11
FORM MOVING: [0, 5], to: [0, 12]
FORM MOVING: [0, 7], to: [0, 14]
FORM MOVING: [0, 6], to: [0, 13]

// Elements 0-4 do not move. They stay as the first 5 elements in the tableview

这适用于任意次数迭代的第一次尝试。当我下次第一次将表单完全滚动到 View 之外,然后重试显示/隐藏字段时,此日志保持不变。 (所有相同的日志,但因 EXC_BAD_INSTRUCTION 而崩溃)。这就是为什么我认为它与索引算术无关。

以下是在更新数据模型以反射(reflect)新状态后调用的 PerformBatchUpdates 中的删除、添加和移动逻辑:

tableView.deleteRows(at: toRemove, with: .none)
tableView.insertRows(at: toAdd, with: .none)

for (key, value) in toMove {
print("FORM MOVING: \(key), to: \(value)")
tableView.moveRow(at: key, to: value)
}
// toRemove, toAdd and toMove are populated with indexes you see above.

最佳答案

深入研究在 cellForRow(atIndexPath...) 中渲染单元格的所有逻辑后,我发现其中一个单元格触发了一个调用链,导致底层数据模型更新,而无需重新加载表格 View 。 (它在 TableView 已经被重新加载的同时替换了数据源中的一项 - 无意中)。

这解释了只有在对底层数据源进行这种不希望的不同步更新之后,我才会在执行下一个 PerformBatchUpdates 操作时发生崩溃。 (或者即使我这样做了:tableView.beginUpdates(), tableView.endUpdates() <-使用相同的 EXC_BAD_INSTRUCTION 也会崩溃)。

因此,在调用 PerformBatchUpdates 或 .beginUpdates()/.endUpdates() 之前,数据源不同步是问题所在。一旦我删除了对数据源的意外更改,performBatchUpdates 就会正常运行和动画 - 只要在它的 block 中数据源更新也与 TableView 上的添加/插入/移动操作相匹配。

由于cellForRow(...)中事件链的复杂性,我花了很长时间才找到

关于 swift ,UIKit : How can I diagnose EXC_BAD_INSTRUCTION in UIKit on tableView. PerformBatchUpdates(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59074565/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com