避免致命的崩溃
Avoiding fatal crashes
我已经调试了一段时间的应用程序,并准备将其上传到应用程序商店。然而,我仍然偶尔会遇到难以复制或调试的崩溃——例如,以奇怪的顺序按下按钮时。如果我把这些序列写下来,我可以调试,但当我没有写下来时不可避免地会发生这种情况,而且这些序列很难复制。
我知道我需要收工了,将未来的错误修复留到下一个版本。我已经删除了我在测试中使用的所有 abort() 语句。但是,有时我不会遇到让您关闭应用程序并重新打开的崩溃,而是会导致无法在不重新安装的情况下打开应用程序。例如,这刚刚发生,
'NSGenericException', reason: '*** Collection <__NSCFSet: 0x174a41b90> was mutated while being enumerated.'
这是由于在后台同步到云期间切换 VC 造成的。
我可以忍受只需要重新打开的崩溃,但不能忍受导致应用程序无法使用的崩溃。是否有任何关于崩溃类型的指南可以帮助您专注于真正致命的崩溃?
或者您能做些什么来防止应用程序变砖导致崩溃?
你应该解决这个问题。由于您有包含该错误消息的崩溃日志,您知道哪种方法会引发问题,因此您在修复它方面有了一个良好的开端,即使问题以各种方式表现得不一致 and/or 也是如此。
但偶尔的崩溃对您来说似乎并没有太大的不便,但这是获得 1 星评价和不满意客户的最快方式。我怀疑您很快就会后悔分发了一个已知的、容易重现的崩溃问题的应用程序。
但是,一些观察:
听起来您的后台更新进程正在改变主线程使用的模型对象。
如果可能的话,我建议小心不要在后台线程中更改任何模型对象,而是填充一个局部变量,并在您准备好更新 UI 因此,将模型更新和 UI 刷新分派到主线程。
如果由于某种原因你不能这样做,你必须使用一些机制同步模型更新的所有交互,例如锁、GCD 串行队列、reader-writer 模型等。这是稍微复杂一点的方法,但是可以做到。
我建议暂时编辑目标的 "scheme" 并打开线程清理程序:
它可能会帮助您识别并更轻松地重现此类问题。您越容易重现问题,就越容易解决问题。
你说:
Or is there anything you can do to keep crashes from bricking app?
听起来 "save" 操作以某种内部不一致的方式将结果留在持久存储中。以下任何一项都会有所帮助,但我建议您尽可能全部执行这三项):
冒着重复自己的风险,修复崩溃(消除问题的根源总是比尝试围绕问题的表现进行编程);
根据您保存结果的方式,您可以使用 atomic
保存操作,这样即使中途失败,也不会保留不一致的状态;如果没有看到说明如何保存结果的代码片段,我们无法建议您应该如何操作,但这通常是一种选择;
确保如果读取持久存储的 "load" 进程可能失败,它会优雅地执行,而不是崩溃;看看您是否可以将其置于应用程序在启动过程中失败的这种状态,然后仔细调试启动过程中发生的导致应用程序失败的情况,以及永久存储中的这组特定数据。在 "devices" 部分,有一个选项可以下载与应用程序关联的数据,因此您可以仔细诊断发生了什么。
我已经调试了一段时间的应用程序,并准备将其上传到应用程序商店。然而,我仍然偶尔会遇到难以复制或调试的崩溃——例如,以奇怪的顺序按下按钮时。如果我把这些序列写下来,我可以调试,但当我没有写下来时不可避免地会发生这种情况,而且这些序列很难复制。
我知道我需要收工了,将未来的错误修复留到下一个版本。我已经删除了我在测试中使用的所有 abort() 语句。但是,有时我不会遇到让您关闭应用程序并重新打开的崩溃,而是会导致无法在不重新安装的情况下打开应用程序。例如,这刚刚发生,
'NSGenericException', reason: '*** Collection <__NSCFSet: 0x174a41b90> was mutated while being enumerated.'
这是由于在后台同步到云期间切换 VC 造成的。
我可以忍受只需要重新打开的崩溃,但不能忍受导致应用程序无法使用的崩溃。是否有任何关于崩溃类型的指南可以帮助您专注于真正致命的崩溃?
或者您能做些什么来防止应用程序变砖导致崩溃?
你应该解决这个问题。由于您有包含该错误消息的崩溃日志,您知道哪种方法会引发问题,因此您在修复它方面有了一个良好的开端,即使问题以各种方式表现得不一致 and/or 也是如此。
但偶尔的崩溃对您来说似乎并没有太大的不便,但这是获得 1 星评价和不满意客户的最快方式。我怀疑您很快就会后悔分发了一个已知的、容易重现的崩溃问题的应用程序。
但是,一些观察:
听起来您的后台更新进程正在改变主线程使用的模型对象。
如果可能的话,我建议小心不要在后台线程中更改任何模型对象,而是填充一个局部变量,并在您准备好更新 UI 因此,将模型更新和 UI 刷新分派到主线程。
如果由于某种原因你不能这样做,你必须使用一些机制同步模型更新的所有交互,例如锁、GCD 串行队列、reader-writer 模型等。这是稍微复杂一点的方法,但是可以做到。
我建议暂时编辑目标的 "scheme" 并打开线程清理程序:
它可能会帮助您识别并更轻松地重现此类问题。您越容易重现问题,就越容易解决问题。
你说:
Or is there anything you can do to keep crashes from bricking app?
听起来 "save" 操作以某种内部不一致的方式将结果留在持久存储中。以下任何一项都会有所帮助,但我建议您尽可能全部执行这三项):
冒着重复自己的风险,修复崩溃(消除问题的根源总是比尝试围绕问题的表现进行编程);
根据您保存结果的方式,您可以使用
atomic
保存操作,这样即使中途失败,也不会保留不一致的状态;如果没有看到说明如何保存结果的代码片段,我们无法建议您应该如何操作,但这通常是一种选择;确保如果读取持久存储的 "load" 进程可能失败,它会优雅地执行,而不是崩溃;看看您是否可以将其置于应用程序在启动过程中失败的这种状态,然后仔细调试启动过程中发生的导致应用程序失败的情况,以及永久存储中的这组特定数据。在 "devices" 部分,有一个选项可以下载与应用程序关联的数据,因此您可以仔细诊断发生了什么。