我遇到了一些我遇到问题的 beta 测试人员的奇怪崩溃。符号化的崩溃报告表明崩溃发生在作为单例的控制器的简单分配中,在 init 调用中,但根据堆栈跟踪,看来我所拥有的代码init
实际上并不是崩溃所在的位置。以下是相关代码:
1534| + (UA[REDACTED]PlayerController*)sharedInstance
1535| {
1536| @synchronized(self)
1537| {
1538| if (sharedInstance == nil)
1539| sharedInstance = [[UA[REDACTED]PlayerController alloc] init];
1540| }
1541| return sharedInstance;
1542| }
这以前从未崩溃过,而且代码最近也没有任何变化。这是引发的堆栈跟踪:
Thread 5:
0 libSystem.B.dylib 0x33bd52d4 __kill + 8
1 libSystem.B.dylib 0x33bd52c4 kill + 4
2 libSystem.B.dylib 0x33bd52b6 raise + 10
3 libSystem.B.dylib 0x33be9d26 __abort + 62
4 libSystem.B.dylib 0x33be9d7e abort + 62
5 libSystem.B.dylib 0x33bd7980 __assert_rtn + 152
6 libgcc_s.1.dylib 0x32acab4e _Unwind_SjLj_Resume + 26
7 [REDACTED] 0x00060b64 +[UA[REDACTED]PlayerController sharedInstance] (UA[REDACTED]PlayerController.m:1540)
8 [REDACTED] 0x00063e6c -[UA[REDACTED]PlayerViewController setupControlViews] (UA[REDACTED]PlayerViewController.m:224)
9 [REDACTED] 0x00062ce0 -[UA[REDACTED]PlayerViewController viewDidLoad] (UA[REDACTED]PlayerViewController.m:268)
10 UIKit 0x320a0270 -[UIViewController view] + 104
…
关于这个神秘的崩溃是什么以及它可能来自哪里的任何想法?
更新 1
它似乎与核心数据和迁移有关。我能够复制它,但根本原因仍然未知。我在这个版本中有一些自动迁移,看起来虽然可以读取一些 NSManagedObjects,但其他人正在抛出这个异常,特别是在 NSManagedObjects 关系上。可能根本就没有关系
PlayerController
。任何核心数据专家都有一些见解?
更新 2
这是我找到重现它的方法

和相关代码后崩溃的调用堆栈:
if (resultArray && [resultArray count]) {
for (MixAudio *ma in resultArray) {
Audio *audio = [ma valueForKey:LOCAL_MIX_AUDIO_AUDIO_KEY];
if (audio) {
[returnArray addObject:audio];
}
}
为了帮助解释我做了什么来重现它,我必须稍微解释一下数据结构。我有Mix
和Audio
项目。混音有很多音频,音频属于很多混音。这是对 MixAudio 对象的简单关系调用以获取音频。现在,这只是在我将数据库还原到新版本后才崩溃。
我的设置中的数据库备份意味着压缩数据库以保存数据,然后在还原时解压缩。此崩溃仅在还原过程之后发生。更复杂的是,有 3 个带有映射模型的数据库版本。因为这个过程在版本控制之前对我有用,所以我觉得我的版本中的某些东西导致了这个崩溃。
所有其他数据都很好,可以访问,甚至保存。不知何故,这个单一的提取导致了问题。设置持久存储或托管对象模型时没有错误或警告。此外,可以很好地创建和访问新的 Mix 对象,只有较旧的提取(在还原之前位于数据库中)失败。
如果我没有发现错误,控制台会打印:
Assertion failed: (_Unwind_SjLj_Resume() can't return), function _Unwind_SjLj_Resume, file /SourceCache/libunwind/libunwind-24.1/src/Unwind-sjlj.c, line 326.
在崩溃线周围放置 atry/catch
可以让我检查根本崩溃原因:
Error: NSRangeException: *** -[NSMutableArray objectAtIndex:]: index 4294967295 beyond bounds [0 .. 16]
valueForKey
但这对于一个简单的电话来说毫无意义(至少对我来说) 。4294967295 = 2^32-1 这意味着如果有帮助,索引 var 可能设置为 -1。我在这里迷路了。
[已解决] 更新 3
我在版本控制中是对的 :) 我重新阅读了Zarra 书中关于版本控制的部分,并且有一个重要的DOH时刻。这是我第一次拥有具有 3 个数据库版本的应用程序。我在我的应用程序中使用映射模型,我天真地假设核心数据能够使用一个模型从 1-2 映射,然后使用下一个模型映射 2-3。当我意识到我没有 1-3 映射模型时,我真的撞到了头。为了测试它,我快速添加了一个,一切都像黄油一样光滑。现在我只需要回去使用他的
Progressive Data Migration
样本来让我的生活更轻松,因为我继续使用更多版本的数据库。
我希望 Zarra 开车经过这里并回答一些事情……任何事情……这样我就可以给他分数了 :)