Search code examples
keyboardios9uialertcontroller

Show UIAlertController over keyboard


In iOS 8 and lower show a UIActionSheet when keyboard is presented will present the action sheet over the keyboard. With iOS 9 this is no longer the case.

In my app we have a chat functionality and want the show a action over the keyboard. We used to use UIActionSheet which worked fine until iOS 8. In iOS 9 the action sheet is present behind the keyboard. I've tried both UIActionSheet and UIAlertController.

What we want is a action sheet like in messages.app Action sheet in messages app.

I've tried placing the action sheet in it own window and overriding canBecomeFirstResponder which just made the keyboard disappear.


Solution

  • I have implemented exactly this in our app. The trick is to have the alert controller appear on a different window. This is how the UIActionSheet implementation does it, and works great on iOS 8, but on 9, Apple has moved the keyboard implementation to a window which has a very high window level (10000000). The fix is to give your alert window an even higher window level (as a custom double value, not using the provided constants).

    When using a custom window which will have transparency, make sure to read my answer here, regarding background color, to prevent window becoming black during rotation transitions.

    _alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    _alertWindow.rootViewController = [UIViewController new];
    _alertWindow.windowLevel = 10000001;
    _alertWindow.hidden = NO;
    _alertWindow.tintColor = [[UIWindow valueForKey:@"keyWindow"] tintColor];
    
    __weak __typeof(self) weakSelf = self;
    
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Test" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        weakSelf.alertWindow.hidden = YES;
        weakSelf.alertWindow = nil;
    }]];
    [alert addAction:[UIAlertAction actionWithTitle:@"Test" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        weakSelf.alertWindow.hidden = YES;
        weakSelf.alertWindow = nil;
    }]];
    
    [_alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
    

    enter image description here