3

If I run a clean build and a fresh installation, my app installs and runs just fine, however, if I install the previous released version, then overwrite that release with the new version, it will crash on first run.

Steps to Reproduce

  1. Install and run previous version of my app (1.4) on iPhone 4.
  2. Close app and kill process.
  3. Checkout latest version (2.0)
  4. Delete build directory
  5. Install and run
  6. Crash

I'm running Xcode 3.2.5, the 4.2 SDK. My iPhone 4 is 4.2.1.

If you look at the crash logs, it looks like I've got a bad connection in one of my NIBs, but there is no object trying to connect to a 'view' property in my AppController. Sometimes an identical crash will occur except it will say this class is not key value coding-compliant for the key activityIndicator. This is also wonky, since grep has confirmed that I've got nothing in my project called activityIndicator.

I have three questions:

  • Why is my app crashing?
  • Does anyone have any ideas on further debugging I can do? I've run out of ideas on how to fix this.
  • It's possible (likely?) that when Xcode installs a build on your device that it takes shortcuts that will not be taken when the app is installed from the store. Does anyone know if this is the case and, if so, do you know of a way to simulate the exact app store installation process so I can make sure that I don't kill my app for all the upgraders?

Crash Log

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
)

--

I should add that the app crashes before it gets to any of my code, i.e. application:didFinishLaunchingWithOptions: and applicationDidFinishLaunching: are never called.

kubi
  • 48,104
  • 19
  • 94
  • 118
  • The clue is: "this class is not key value coding-compliant for the key activityIndicator" It means that the nib is telling the framework that there is (or was) an activityIndicator IBOutlet on the AppController. You've probably removed it in XCode but never updated your nib. Open your nib and inspect the properties of the AppController as its defined in InterfaceBuilder. – Cliff Feb 10 '11 at 14:54
  • That's not the problem, Cliff. The app loads and runs perfectly on a clean install. – kubi Feb 10 '11 at 14:58
  • I assume that when you update an app from the AppStore that the app bundle is completely removed and replaced, which would fix this problem. I don't want to submit my binary until I know for sure, though. – kubi Feb 10 '11 at 15:01

3 Answers3

4

I finally figured out what the problem is. The previous version of my app was not localized, so all NIBs were at the top level of the app package. The latest version of my app is localized, so all NIBs are in an en.lproj directory. When Xcode deploys the app to the device (and the simulator) it does not replace the entire package, it just copies the build files into the existing package. This results in two versions of my NIBs, an outdated version at the top level of my app bundle and the current version inside a subfolder.

When the app is setup it's pulling the topmost NIB, which is the incorrect NIB, which causes a crash. As a result, I will need to actually deploy an .ipa to my phone in order to test the upgrade.

kubi
  • 48,104
  • 19
  • 94
  • 118
2

The problem is obviously that the old version leaves some data on the filesystem and the new version can't pick it up properly. If you're saving something like the location of a file, make sure it only stores paths relative to the app's directory, not the whole system paths as the internal bundle ids change during updating.

tux91
  • 1,674
  • 10
  • 16
  • That's what I suspected too, but the application load process never makes it into my code; the only resources that are loaded are those that are loaded automatically, like the MainWindow.xib and the first viewController in the navigation stack. Both of those files are loaded from the bundle, so there's no chance (that I'm aware of) for the associated resources to be absolute file paths. – kubi Feb 10 '11 at 13:54
  • 1
    Try making ipas out of the two versions, install them in iTunes, sync and test. This should remove any chance of xcode interfering – tux91 Feb 10 '11 at 19:52
1

This has nothing to do with file system locations. You have an inconsistancy with your nib and your application logic. My guess is you've done something like change the type of AppController used in your project without updating your nib or changed one of the IBOutlets without updating your nib. What's happening is during the deserialization of the nib the framework tries to connect something like an IBOutlet that used to exist in the old controller type but no longer exists in the new AppController type.

Cliff
  • 10,586
  • 7
  • 61
  • 102
  • If that's the case, shouldn't the new nib overwrite the old nib? The app loads perfectly on a clean install, so there's nothing wrong with any of my controllers or nibs. The more I look into this, the more confident I'm becomming that this crash is an artifact of how Xcode loads new code over an existing app. It's probably failing to clean up something that should be cleaned up. – kubi Feb 10 '11 at 14:55
  • Ah, I missed youre mentioning that it builds, installs, and runs fine with a clean. IF a dirty build/run fails followed by a successful clean build & run then yes, it could be some of the shortcut XCode takes to save you time during development. – Cliff Feb 10 '11 at 14:59