Back to Blog
iOS5 Upgrade Nightmares

Like most iOS developers, we have been spending a lot of time rushing around getting all of our apps ready for iOS 5. It has been “trying”, to put it mildly. Simple things that we’ve taken for granted ever since iOS 3.0 suddenly don’t work, but leave very little debugging trace for us to follow. After countless hours researching and debugging, and now that the NDA is gone, here’s the list of biggest issues we’ve found:

Modal View Controllers

self.parentViewController is now nil in iOS5, so any code like this [[self parentViewController] dismissModalViewControllerAnimated:YES]; will no longer work. In iOS5, change this to [self dismissModalViewControllerAnimated:YES];, but if you want to maintain backwards compatibility with iOS 4.x, you will need to add a conditional because this won’t work in the older versions.

More Modal View Controllers

In iOS5, suddenly some of my modal view controllers weren’t presenting at all. They worked great in older iOS versions. It turns out that iOS guidelines don’t want model view controllers to be presented in viewDidLoad or in viewWillAppear, but this was not enforced in pre iOS5 versions. I guess I got pretty lazy in this respect and had a few modals presented in viewDidLoad. Especially in instances where I wanted to show a login or loading screen.

After moving all of these [self presentModalViewController:ctrl animated:NO]; calls to (void)viewDidAppear:(BOOL)animated, they now work. Sounds great, but there’s still one more step — the benefit of using viewDidLoad to present these is that it’s only called once when the view is loaded, but viewDidAppear is called (as you can guess) every time the view becomes visible. So for this to work, make sure to set a flag that makes sure the modal view controller snippet only gets called once. For me, it looks like this:

if (!viewLoaded) {
    LoadingViewController *ctrl = [[LoadingViewController alloc] initWithNibName:@"LoadingViewController" bundle:nil];
        [self presentModalViewController:ctrl animated:NO];
    [ctrl release];    
    NSLog(@"presented");
    viewLoaded = YES;
}

View Lifecycle Changes

I ran into this issue while firefighting some major customer complaints, so the exact process I took to solve this isn’t perfectly clear in my brain. But here’s the bottom line — After (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions, the order that viewDidLoad in the root or first view gets called has changed. In iOS5, viewDidLoad gets called right away, where in older iOS versions, (void)applicationDidBecomeActive:(UIApplication *)application got called before viewDidLoad. This probably won’t affect too many apps, but we happened to be checking for updates there and were taking action in viewDidLoad based on the results. Once again, this was tough to solve while maintaining backwards compatibility.

UIWebView Issues

This one just came up this morning, where the app crashes after I load a PDF file into a UIWebView and then pop the view controller. Once again, no issues pre iOS5, and this error has the joy of no stack trace and no debugging information. I’m still researching the issue and will update this post when I figure it out.

Update

The webview issue seems to have been a fluke with the debugger. If I remove the Break on all Exceptions breakpoint, it functions fine. Before removing that breakpoint, I tried pressing play again after it stopped at the exception. Go figure, it would continue running the app without issue. After some additional research on Stack Overflow, many others had this exact issue and were all able to solve it by removing the exception breakpoint.

Tags: ios