Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIAlertController is moved to buggy position at top of screen when it calls `presentViewController:`

Presenting a view from a UIAlertController moves the alert to a buggy position at the top-left corner of the screen. iOS 8.1, device and simulator.

We have noticed this in an app when we attempt to present a view from the current "top-most" view. If a UIAlertController happens to be the top-most view we get this behavior. We have changed our code to simply ignore UIAlertControllers, but I'm posting this in case others hit the same issue (as I couldn't find anything).

We have isolated this to a simple test project, full code at the bottom of this question.

  1. Implement viewDidAppear: on the View Controller in a new Single View Xcode project.
  2. Present aUIAlertController alert.
  3. Alert controller immediately calls presentViewController:animated:completion: to display and then dismiss another view controller:

The moment the presentViewController:... animation begins, the UIAlertController is moved to the top-left corner of the screen:

Alert has moved to top of screen

When the dismissViewControllerAnimated: animation ends, the alert has been moved even further into the top-left margin of the screen:

Alert has moved into the top-left margin of the screen

Full code:

- (void)viewDidAppear:(BOOL)animated {     // Display a UIAlertController alert     NSString *message = @"This UIAlertController will be moved to the top of the screen if it calls `presentViewController:`";     UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"UIAlertController iOS 8.1" message:message preferredStyle:UIAlertControllerStyleAlert];     [alert addAction:[UIAlertAction actionWithTitle:@"I think that's a Bug" style:UIAlertActionStyleCancel handler:nil]];     [self presentViewController:alert animated:YES completion:nil];      // The UIAlertController should Present and then Dismiss a view     UIViewController *viewController = [[UIViewController alloc] init];     viewController.view.backgroundColor = self.view.tintColor;     [alert presentViewController:viewController animated:YES completion:^{         dispatch_after(0, dispatch_get_main_queue(), ^{             [viewController dismissViewControllerAnimated:YES completion:nil];         });     }];      // RESULT:     // UIAlertController has been moved to the top of the screen.     // http://i.imgur.com/KtZobuK.png } 

Is there anything in the above code that would be causing this issue? Do any alternatives exist that would allow bug-free presentation of a view from a UIAlertController?

rdar://19037589
http://openradar.appspot.com/19037589

like image 806
pkamb Avatar asked Nov 19 '14 23:11

pkamb


1 Answers

I encountered a situation where sometimes a modal view would present itself on top of a an alert (silly situation, I know), and the UIAlertController could appear in the top left (like the 2nd screenshot of the original question), and I found a one-liner solution that seems to work. For the controller that's about to be presented on the UIAlertController, change its modal presentation style like so:

viewControllerToBePresented.modalPresentationStyle = .OverFullScreen 

This should be done just before you call presentViewController(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion completion: (() -> Void)?)

like image 163
senmu Avatar answered Sep 19 '22 14:09

senmu