iOS应用程序在升级时崩溃。

3
如果我进行干净的构建和全新的安装,我的应用程序可以正常安装和运行,但是,如果我安装之前发布的版本,然后用新版本覆盖该版本,则会在第一次运行时崩溃。
重现步骤:
1. 在 iPhone 4 上安装并运行我应用程序的先前版本(1.4)。 2. 关闭应用程序并终止进程。 3. 检出最新版本(2.0)。 4. 删除构建目录。 5. 安装并运行。 6. 崩溃。
我正在运行 Xcode 3.2.5,4.2 SDK。我的 iPhone 4 是 4.2.1。
如果您查看崩溃日志,似乎我的 NIB 中有一个错误的连接,但是没有任何对象尝试连接到我的 AppController 中的 'view' 属性。有时会发生完全相同的崩溃,只是会说“此类不符合键值编码-compliant 的 activityIndicator”。这也很奇怪,因为 grep 已经确认我的项目中没有叫做 activityIndicator 的东西。
我的三个问题是:
1. 我的应用程序为什么会崩溃? 2. 是否有人有更多的调试想法?我已经没有办法修复它了。 3. 当 Xcode 在您的设备上安装构建时,可能会采取捷径,而在从商店安装应用程序时不会采取这些捷径。是否有人知道是否是这种情况,如果是,是否知道一种模拟确切应用商店安装过程的方法,以便我可以确保不会为所有升级者杀死我的应用程序?
崩溃日志:
2011-02-10 06:58:32.115 TheApp[132:307] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppController 0x14d680> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key view.'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x33ac0987 __exceptionPreprocess + 114
    1   libobjc.A.dylib                     0x3347b49d objc_exception_throw + 24
    2   CoreFoundation                      0x33ac0705 -[NSException dealloc] + 0
    3   Foundation                          0x3367db4f -[NSObject(NSKeyValueCoding) setValue:forUndefinedKey:] + 182
    4   Foundation                          0x3367d03b _NSSetUsingKeyValueSetter + 90
    5   Foundation                          0x3367eda3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 194
    6   Foundation                          0x33630b17 -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 130
    7   UIKit                               0x3224c60f -[UIRuntimeOutletConnection connect] + 66
    8   CoreFoundation                      0x33a63fc7 -[NSObject(NSObject) performSelector:] + 18
    9   CoreFoundation                      0x33a6cd51 -[NSArray makeObjectsPerformSelector:] + 388
    10  UIKit                               0x3224b577 -[UINib instantiateWithOwner:options:] + 586
    11  UIKit                               0x3224cb39 -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] + 92
    12  UIKit                               0x3209e871 -[UIApplication _loadMainNibFile] + 96
    13  UIKit                               0x3209a1fd -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 180
    14  UIKit                               0x3206648b -[UIApplication handleEvent:withNewEvent:] + 1114
    15  UIKit                               0x32065ec9 -[UIApplication sendEvent:] + 44
    16  UIKit                               0x32065907 _UIApplicationHandleEvent + 5090
    17  GraphicsServices                    0x33b0ef03 PurpleEventCallback + 666
    18  CoreFoundation                      0x33a556ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
    19  CoreFoundation                      0x33a556c3 __CFRunLoopDoSource1 + 166
    20  CoreFoundation                      0x33a47f7d __CFRunLoopRun + 520
    21  CoreFoundation                      0x33a47c87 CFRunLoopRunSpecific + 230
    22  CoreFoundation                      0x33a47b8f CFRunLoopRunInMode + 58
    23  UIKit                               0x32099309 -[UIApplication _run] + 380
    24  UIKit                               0x32096e93 UIApplicationMain + 670
    25  TheApp                              0x00002781 main + 88
    26  TheApp                              0x00002724 start + 40
)

--

我应该补充一点,这个应用程序在执行到我的任何代码之前就崩溃了,也就是说,application:didFinishLaunchingWithOptions:applicationDidFinishLaunching:从未被调用。


提示是:“此类不符合键值编码的activityIndicator关键字。” 这意味着nib告诉框架在AppController上有(或曾经有)一个activityIndicator IBOutlet。 您可能已在XCode中将其删除,但从未更新过nib。 打开您的nib并检查InterfaceBuilder中定义的AppController的属性。 - Cliff
这不是问题,克利夫。该应用程序在干净的安装上加载和运行完美。 - kubi
我猜想,当你从AppStore更新应用程序时,应用程序捆绑包会被完全删除并替换,从而解决此问题。不过,在我确信之前,我不想提交我的二进制文件。 - kubi
3个回答

4
我最终弄清了问题所在。我的应用程序的先前版本没有进行本地化,因此所有的NIB文件都在应用程序包的顶层。我的最新应用程序进行了本地化,在en.lproj目录中放置了所有的NIB文件。当Xcode将应用程序部署到设备(和模拟器)时,它不会替换整个包,而只是将构建文件复制到现有包中。这导致我的NIB文件存在两个版本,一个过时的版本位于应用程序包的顶层,而当前版本位于子文件夹内。
当应用程序被设置时,它会拉取最顶层的NIB文件,这是错误的NIB文件,导致崩溃。因此,我需要实际部署一个.ipa文件到我的手机上,以便测试升级。

2
显然问题在于旧版本在文件系统上留下了一些数据,而新版本无法正确地获取这些数据。如果您保存的是文件位置之类的东西,请确保它仅存储相对于应用程序目录的路径,而不是整个系统路径,因为内部捆绑包ID在更新过程中会发生变化。

这也是我怀疑的,但应用程序加载过程从未进入我的代码;仅加载的资源是自动加载的资源,例如MainWindow.xib和导航栈中的第一个视图控制器。这两个文件都是从捆绑包中加载的,因此我不知道是否有关联的资源是绝对文件路径的机会。 - kubi
1
尝试制作这两个版本的ipa文件,安装到iTunes中,同步并进行测试。这样就可以消除Xcode干扰的任何可能性。 - tux91

1
这与文件系统位置无关。您的 nib 和应用程序逻辑存在不一致。我猜测您可能已经更改了项目中使用的 AppController 类型,但没有更新您的 nib,或者更改了其中一个 IBOutlets,但没有更新您的 nib。正在发生的是,在反序列化 nib 期间,框架尝试连接类似于旧控制器类型中存在但在新的 AppController 类型中不存在的 IBOutlet。

如果是这样,新的nib不应该覆盖旧的nib吗?在干净的安装上,应用程序可以完美加载,因此我的控制器或nib没有任何问题。我越看越有信心,这个崩溃是Xcode如何在现有应用程序上加载新代码的产物。它可能未能清理应该清理的东西。 - kubi
啊,我错过了你提到的它可以在干净的环境下构建、安装和运行。如果脏构建或运行失败,然后进行成功的干净构建和运行,那么可能是XCode为节省开发时间而采取的某些快捷方式导致的。 - Cliff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接