Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception "Application tried to present modally an active controller" crash in iOS 8 only

Tags:

ios

uikit

ios8

UIPopoverController *popCtrl = [[UIPopoverController alloc] initWithContentViewController:self.rootViewController.navigationController];
popCtrl.delegate = self;
[popCtrl presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

This code is in a button action, where the button is the "sender".

The line with presentPopoverFromBarButtonItem causes an exception to be thrown with the reason: Application tried to present modally an active controller DetailViewController: 0x15a54c00. DetailViewController is "self" in this case and it is only a delegate to popCtrl, so I don't see how it could be trying to present modally. It's supposed to be presenting rootViewController.navigationController.

As you may have guessed from the names, rootViewController and detailViewController are inside a SplitViewController, but prior to trying to present rootViewController with the the popover, it is removed from the SplitViewController.

This only happens on iOS 8 when built with the iOS 8 SDK. It's also not 100% reproducible. Most of the time this exception occurs, but sometimes after I restart the app it does not occur at all until I rerun the app, then it starts happening all the time again. (I put it in a try/catch so I know it can occur more than once per run.)

I'm almost positive this is yet another iOS 8 bug in the SDK, but has anyone come up with a workaround?

like image 490
Steve Avatar asked Nov 11 '22 00:11

Steve


1 Answers

I faced the same problems while updating some app, which was initially developed at the times of iOS 5.0. Removing the controller from the UISplitViewController right before using it in the popover did not work, neither did it help to switch to the newer UIPopoverPresentationController.

However, I was able to swipe-in my (master) controller from the left side. More or less, I discovered that "feature" by accident, so I looked up where this came from and found this in Apple's iOS SDK 5.1 release notes:

In 5.1 the UISplitViewController class adopts the sliding presentation style when presenting the left view (previously only seen in Mail). This style is used when presentation is initiated either by the existing bar button item provided by the delegate methods or by a swipe gesture within the right view. No additional API adoption is required to obtain this behavior, and all existing API, including that of the UIPopoverController instance provided by the delegate, will continue to work as before. If the gesture cannot be supported in your app, set the presentsWithGesture property of your split view controller to NO to disable the gesture. However, disabling the gesture is discouraged because its use preserves a consistent user experience across all applications.

(Source: iOS 5.1 Release Notes, requires Apple Developer Login)

I didn't test what happens if you set the mentioned property to NO and if it releases the controller, but I wouldn't put too much hope on that.

So even after removing it manually from the UISplitViewController, my view controller was still active on that hidden swipeable pane, which appears to happen internally in the SDK. I'm aware of the fact that this still worked fine until iOS 7.x, but I actually consider that as tolerated bug now, closed with iOS 8.0.

I ended up abandoning the popover completely and using the default UISplitViewController behaviour of iOS 5.1 and above. For some extra tweaking, you can change UISplitViewController.preferredDisplayMode to fit your needs, this saved me a lot of time to upgrade old code which never heard of auto layout.

like image 167
Jerrot Avatar answered Nov 14 '22 22:11

Jerrot