Reputation: 3181
I have code that is triggered on launch only after the app is upgraded or installed. I want to debug this code, but can't think of a way to do it.
I can't launch the app with Xcode because it would overwrite the existing app and wouldn't trigger the update.
I can't attach Xcode to the process manually because the code I want to debug will have executed by the time I get Xcode attached.
Is there someway of pulling this off that I'm missing?
Upvotes: 27
Views: 5759
Reputation: 124997
Use the "Wait for MyApp.app to launch" option.
In Xcode, hold down the Option key and choose Product->Run... (the ellipses are added when you hold Option down). This will bring up the scheme editor, with the Run scheme selected. Click on the Info tab, and on the resulting Info panel you'll see a radio group labelled "Launch" with two options: "Automatically" and "Wait for MyApp.app to launch". If you select the second option, Xcode will start the debugger and wait for you to launch your application manually. You can set a breakpoint at the beginning of the code you want to debug, and the debugger will stop there.
Reset the app to its previous state.
You may want to consider adding some code that resets the app to whatever state it was in before the upgrade. This can be debug code that's excluded from the release build. Debugging problems that require you to re-install the app every time you want to run through your debug can take a lot of time. Even just having to restart the app at every debug cycle eats up a lot of your time. It's very often worthwhile to spend a little extra time adding a button to your app that undoes whatever changes you're making so that you can do them again.
Unit test.
One great way to debug code that deals with app states that are difficult to recreate is to write unit tests. In a test, you can create any state you want. You can even create app states that may be impossible to recreate in your app. And you can debug that code over and over again. Like the previous solution, it takes a little more time to write the code up front, but you'll save so much time on each iteration of your debug cycle that its well worth it. Even better, you can add the test to your build process so to help ensure that the functionality doesn't break later.
Upvotes: 55
Reputation: 26952
I also have some code that I only run on upgrades, i have this method below which I use at the end of applicationDidFinishLaunching. I can debug this too:
- (void) determineWhetherToForceSync {
NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *savedVersionKey = @"savedVersionKey";
NSString *savedVersion = [[NSUserDefaults standardUserDefaults] valueForKey:savedVersionKey];
if (!savedVersion) {
//This is a fresh install....
} else {
//They have a saved version, so check if it's the same as current version
if (![currentVersion isEqualToString:savedVersion]) { //They have done an upgrade
//This is an update
} //.... else they are starting the app on a second attempt
}
//Save the current version
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:savedVersionKey];
}
To re-test, delete the app and re-install. Or change your version number.
Upvotes: 0