Resolution: While trying to recreate this bug in a fresh project to submit to Apple, I discovered that it is specific to iPhone OS 2.1, and compiling for 2.2 fixes the problem. Stephen, thanks for your help; I'll be accepting your answer since it would have worked if the bug still existed or I wasn't willing to compile for 2.2.
I have an app which is radically changing its database schema in a way that requires me to transform old-style records to new-style ones in code. Since users may store a lot of data in this app, I'm trying to display a modal view controller with a progress bar while it ports the data over (i.e. as the very first thing the user sees). This view controller's viewDidAppear:
begins a database transaction and then starts a background thread to do the actual porting, which occasionally uses performSelectorInMainThread:withObject:waitUntilDone:
to tell the foreground thread to update the progress bar.
The problem is, viewDidAppear:
is being called twice. I noticed this because that "start a transaction" step fails with a "database busy" message, but setting a breakpoint reveals that it is indeed called two times—once by -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]
, and again by -[UIViewController modalPresentTransitionDidComplete]
. Those names appear to be private UIViewController methods, so I'm guessing this is either a framework bug, or I'm doing something UIKit isn't expecting me to do.
Two relevant code excerpts (some irrelevant code has been summarized):
- (void)applicationDidFinishLaunching:(UIApplication *)application {
(register some default settings in NSUserDefaults)
// doing this early because trying to present a modal view controller
// before the view controller is visible seems to break it
[window addSubview:[self.navigationController view]];
// this is the method that may present the modal view
[self.databaseController loadDatabaseWithViewController:self.navigationController];
if(!self.databaseController.willUpgrade) {
[self restoreNavigationControllerState];
}
}
And from my DatabaseController class:
- (void)loadDatabaseWithViewController:(UIViewController*)viewController {
(open the new database)
(compute the path the old database would live at if it existed)
if([[NSFileManager defaultManager] fileExistsAtPath:oldDBPath]) {
(open the old database)
[viewController presentModalViewController:self animated:NO];
}
}
So, is there something I'm screwing up here, or should I file a bug report with Apple?