Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to dismiss UIAlertController with unknown presenter

My application crashed, and it must be because of UIAlertController.

This issue occurs only on iOS 8.x where UIAlertController is available. The strange fact is that my application does not use UIAlertViewController nor UIAlertView.

The reports tell me:

Trying to dismiss UIAlertController <UIAlertController: 0x172c5d80> with unknown presenter.

How this can happen?

I thought about

  1. Undo System AlertView displayed thanks to the shake gesture
  2. WebView deallocated while a prompt or a generic dialog is still on screen
  3. Low battery alert

but not one of this cases drive me to the crash.

What the crash log suggests to me is the fact that the OS shows an AlertView that will be attached to my application window and in some circumstances loose the parent view controller that presented the UIAlertViewController.

Any ideas how to find the issue?

Here the stack trace

_________________________________
0    CoreFoundation                         0x2bc0c45f __exceptionPreprocess + 127
1    libobjc.A.dylib                        0x39c79c8b objc_exception_throw + 36
2    CoreFoundation                         0x2bc0c3a5 +[NSException raise:format:] + 110
3    UIKit                                  0x2f4ad13d -[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:] + 414
4    UIKit                                  0x2f4acf97 -[UIAlertController _dismissAnimated:triggeringAction:] + 28
5    UIKit                                  0x2f590a0b -[_UIAlertControllerActionView touchesEnded:withEvent:] + 160
6    UIKit                                  0x2f159567 -[UIWindow _sendTouchesForEvent:] + 520
7    UIKit                                  0x2f152e31 -[UIWindow sendEvent:] + 542
8    UIKit                                  0x2f129759 -[UIApplication sendEvent:] + 194
9    UIKit                                  0x2f39d2f9 _UIApplicationHandleEventFromQueueEvent + 14166
10   UIKit                                  0x2f1281a9 _UIApplicationHandleEventQueue + 1350
11   CoreFoundation                         0x2bbd2fbf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
12   CoreFoundation                         0x2bbd23cf __CFRunLoopDoSources0 + 216
13   CoreFoundation                         0x2bbd0a35 __CFRunLoopRun + 770
14   CoreFoundation                         0x2bb1e3b1 CFRunLoopRunSpecific + 474
15   CoreFoundation                         0x2bb1e1c3 CFRunLoopRunInMode + 104
16   GraphicsServices                       0x3308d201 GSEventRunModal + 134
17   UIKit                                  0x2f18843d UIApplicationMain + 1438
18   MyApp                                  0x00028a07 main (main.mm:16)

EDIT

holes asked about my window initialisation. Here the code of my AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[MyAppCustomWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    _mainViewController = [[MyAppContainerViewController alloc] initWithNibName:nil bundle:nil];
    _mainStatusBarVC = [[MyAppStatusBarVC alloc] initWithRootVC:_mainViewController];

    [self.window setRootViewController:_mainStatusBarVC];
    [self.window makeKeyAndVisible];

    return YES;
}
like image 815
Gabriele Avatar asked Apr 15 '15 11:04

Gabriele


2 Answers

I bet your crash occurred on iPad.

On iPad, from iOS8, UIActionSheet seem to be handled with a UIAlertController

With this code,

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(buttonIndex == 1) return; // Cancel button

    [self doSomeViewControllerDismisses];
}

My app was crashing with the same error you got.
To prevent this, I just dispatch the complex dismiss call on the next MainThread execution, to give to the hidden UIAlertViewController the opportunity to release properly.

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    if(buttonIndex == 1) return; // Cancel button

    dispatch_async(dispatch_get_main_queue(), ^{
        [self doSomeViewControllerDismisses];
    });
}
like image 69
Martin Avatar answered Nov 10 '22 10:11

Martin


A stack trace of this form generally indicates that you have navigated away from a UIViewController whilst an alert that you had it present is still dismissing.

The general remedy for that is to present or dismiss controllers in UIAlertViewDelegate's alertView:didDismissWithButtonIndex: method, since then you're sure that the presenter won't go away during any dismissal.

In your case, if you can't find any reproducible case you could try checking presentedViewController before presenting/dismissing a controller and see if that turns anything up.

But probably if you audit your controller transitions you'll find somewhere that responding to a system alert could programmatically trigger a navigation. Do you have any functionality that throws up a system alert for user authorization, like access to photos or whatever, and them denying it would result in a controller being programmatically dismissed by your error handling? That seems like a reasonably plausible scenario.

like image 24
Alex Curylo Avatar answered Nov 10 '22 08:11

Alex Curylo