由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“意外的启动状态”
Posted
技术标签:
【中文标题】由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“意外的启动状态”【英文标题】:Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unexpected start state' 【发布时间】:2016-04-26 07:10:48 【问题描述】:我奇怪且罕见地重现了在 ios 9 上发生的崩溃。问题是如何解决此问题或导致此异常的原因
如您所见,跟踪不包含我的代码,并且在应用启动时发生崩溃。
Last Exception Backtrace:
0 CoreFoundation 0x0000000180a49900 __exceptionPreprocess + 124
1 libobjc.A.dylib 0x00000001800b7f80 objc_exception_throw + 52
2 CoreFoundation 0x0000000180a497d0 +[NSException raise:format:arguments:] + 104
3 Foundation 0x00000001813bca08 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 84
4 UIKit 0x00000001859f9f34 _prepareForCAFlush + 252
5 UIKit 0x00000001859ff4f0 _beforeCACommitHandler + 12
6 CoreFoundation 0x0000000180a00588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 28
7 CoreFoundation 0x00000001809fe32c __CFRunLoopDoObservers + 368
8 CoreFoundation 0x00000001809fe75c __CFRunLoopRun + 924
9 CoreFoundation 0x000000018092d680 CFRunLoopRunSpecific + 380
10 GraphicsServices 0x0000000181e3c088 GSEventRunModal + 176
11 UIKit 0x00000001857a4d90 UIApplicationMain + 200
12 MyAppName 0x000000010009d200 main (main.m:14)
13 ??? 0x00000001804ce8b8 0x0 + 0
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x00000001805ec140 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001806b4ef8 pthread_kill + 108
2 libsystem_c.dylib 0x000000018055ddac abort + 136
3 MyAppName 0x0000000100805bcc uncaught_exception_handler + 28
4 CoreFoundation 0x0000000180a49c88 __handleUncaughtException + 648
5 libobjc.A.dylib 0x00000001800b823c _objc_terminate() + 108
6 libc++abi.dylib 0x00000001800aaf44 std::__terminate(void (*)()) + 12
7 libc++abi.dylib 0x00000001800aab10 __cxa_rethrow + 140
8 libobjc.A.dylib 0x00000001800b8120 objc_exception_rethrow + 40
9 CoreFoundation 0x000000018092d728 CFRunLoopRunSpecific + 548
10 GraphicsServices 0x0000000181e3c088 GSEventRunModal + 176
11 UIKit 0x00000001857a4d90 UIApplicationMain + 200
12 MyAppName 0x000000010009d200 main (main.m:14)
13 ??? 0x00000001804ce8b8 0x0 + 0
【问题讨论】:
调试器控制台在堆栈跟踪之前写了什么? 什么意思?这是崩溃报告日志的一部分 你能在 Xcode 中调试时重现这个崩溃吗? 不,这仅在发布版本中发生,但您的想法是什么? 查看堆栈中的这一行:3 Foundation 0x00000001813bca08 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 84
。在调试模式下,您将看到一条消息“Assertion failed in ...”。它至少可以帮助您识别失败的源文件。
【参考方案1】:
我遇到了同样的崩溃,reason: 'unexpected start state'
。
这是造成它的原因:
我在 tableView 中有一个单元格,其中包含一个标题设置为电子邮件地址的按钮。当你按下按钮时,我需要它来打开邮件应用程序。
当它打开邮件应用程序时,我的具有 tableView 的 viewController 正在重新加载 traitCollectionDidChange
中的表。
这个tableView.reloadData()
导致了崩溃,很可能是因为应用正在活动状态和后台之间转换。
这是我所做的:
按下电子邮件按钮时使用了回调:class NewsDetailsFooterCell: UITableViewCell
//MARK: - Callbacks
var sendEmail: ((_ emailUrl: URL) -> ())?
//MARK: - IBActions
@IBAction func openAuthorEmail(_ sender: UIButton)
guard let emailAddress = sender.titleLabel?.text, let url = URL(string: "mailto:\(emailAddress)") else return
guard UIApplication.shared.canOpenURL(url) else return
self.sendEmail?(url)
在tableView的cellForRowAt
中使用了回调并修改了一个局部变量,该变量负责在traitCollectionDidChange
函数中阻止tableView的reloadData:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let newsFooterCell = tableView.dequeueReusableCell(withIdentifier: "NewsDetailsFooterCell") as! NewsDetailsFooterCell
//other cell setup
newsFooterCell.sendEmail = [weak self] emailUrl in
self?.viewModel.canReloadTable = false //this is the variable which I need to modify here
UIApplication.shared.open(emailUrl, options: [:], completionHandler: nil)
return newsFooterCell
在traitCollectionDidChange
中,只有当变量canReloadTable
为真时,我才重新加载表的数据:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
super.traitCollectionDidChange(previousTraitCollection)
if #available(iOS 12.0, *)
//using this delegate method to trigger data reload to adapt to Dark/Light modes
guard viewModel.canReloadTable else return
tableView.reloadData()
最后,我在viewDidAppear
中将变量canReloadTable
设置回true
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
viewModel.canReloadTable = true
我希望这个答案对其他人有所帮助,或者至少提供了一个线索,说明在哪里调查潜在问题,因为错误本身根本不是描述性的,我花了大约 1-2 小时调查它并提出解决方案.
【讨论】:
【参考方案2】:另外,在更改应用程序主题时,在traitCollectionDidChange
中重新加载 UICollectionView 时也会出现同样的问题。
我有 updateTheme()
方法,当主题更改时,我会在其中更新某种 UI,例如图层、边框、阴影等。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
super.traitCollectionDidChange(previousTraitCollection)
if #available(iOS 13.0, *), traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)
updateTheme()
我会收到关于终止的消息:
*** Assertion failure in void _UIApplicationDrainManagedAutoreleasePool()(), UIApplication+AutoreleasePool.m:171
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unexpected start state'
将collectionView.reloadData()
添加到updateTheme()
方法时。
当应用程序最小化并更改主题时会发生这种情况。 如此有趣的案例,因为一切都适用于视图、按钮、标签等,但不适用于集合。
一般来说,如果 UIElement 在后台线程中获得更新,应用程序会崩溃,所以每当我们想要更新 UI 时,我们都需要在主线程中更新该 UIElement。
我冒昧地假设当应用程序被最小化时,traitCollectionDidChange
方法并没有在主线程中执行,所以你需要添加DispatchQueue.main.async
以便在主线程中更新 UI。
此更改为我解决了问题,我希望它也对您有所帮助,因为在我的情况下,您添加的简单标志根本不允许在应用程序最小化时更改主题时更新界面。
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
super.traitCollectionDidChange(previousTraitCollection)
if #available(iOS 13.0, *), traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection)
DispatchQueue.main.async
self.updateTheme()
【讨论】:
这也是个好主意!没有测试,但听起来有效。以上是关于由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“意外的启动状态”的主要内容,如果未能解决你的问题,请参考以下文章
目标 C:由于未捕获的异常“NSInvalidArgumentException”而终止应用程序
由于未捕获的异常而终止应用程序 [UIImageView _isResizable]