Keyboard 通过键盘显示UIAlertController

Keyboard 通过键盘显示UIAlertController,keyboard,ios9,uialertcontroller,Keyboard,Ios9,Uialertcontroller,在iOS 8及更低版本中,显示ui操作表当显示键盘时,操作表将显示在键盘上。对于iOS 9,情况不再如此 在我的应用程序中,我们有聊天功能,希望通过键盘显示动作。我们过去使用的是UIActionSheet,它在iOS 8之前运行良好。在iOS 9中,操作表位于键盘后面。我尝试了UIActionSheet和UIAlertController 我们需要的是一个类似于messages.app中的操作表 我试着将操作表放在它自己的窗口中,覆盖可以成为第一响应者,这使得键盘消失。我在我们的应用程序中实现

在iOS 8及更低版本中,显示
ui操作表
当显示键盘时,操作表将显示在键盘上。对于iOS 9,情况不再如此

在我的应用程序中,我们有聊天功能,希望通过键盘显示动作。我们过去使用的是
UIActionSheet
,它在iOS 8之前运行良好。在iOS 9中,操作表位于键盘后面。我尝试了
UIActionSheet
UIAlertController

我们需要的是一个类似于messages.app中的操作表


我试着将操作表放在它自己的窗口中,覆盖
可以成为第一响应者
,这使得键盘消失。

我在我们的应用程序中实现了这一点。诀窍是让警报控制器出现在不同的窗口上。这就是
UIActionSheet
实现的方式,在iOS 8上运行良好,但在iOS 9上,苹果将键盘实现移动到了一个窗口级别非常高(10000000)的窗口。修复方法是为警报窗口提供更高的窗口级别(作为自定义双精度值,不使用提供的常量)

当使用具有透明度的自定义窗口时,请确保阅读有关背景颜色的信息,以防止窗口在旋转转换期间变黑

_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];

使用UIAlertController而不是UIActionSheet

基于Leo Natan的回答,我创建了一个Swift扩展,用于在键盘上显示警报表

在我的简短测试中,alertWindow在警报解除后被解除分配,我认为这是因为在警报之外没有对它的强烈引用。这意味着不需要在UIAlertActions中隐藏或取消分配它

extension UIAlertController {

    func presentOverKeyboard(animated: Bool, completion: (() -> Void)?) {

        let alertWindow = UIWindow(frame: UIScreen.mainScreen().bounds)

        // If you need a white/hidden/other status bar, use an appropriate VC.
        // You may not need a custom class, and you can just use UIViewController()
        alertWindow.rootViewController = whiteStatusBarVC()

        alertWindow.windowLevel = 10000001
        alertWindow.hidden = false

        // Set to a tint if you'd like
        alertWindow.tintColor = UIColor.greenColor()

        alertWindow.rootViewController?.presentViewController(self, animated: animated, completion: completion)
    }
}

private class whiteStatusBarVC: UIViewController {
    private override func preferredStatusBarStyle() -> UIStatusBarStyle {
        return .LightContent
    }
}

从iOS 11开始,Leo提供的答案就被打破了,因为苹果现在阻止您将windowLevel设置为高于
10000000
。修复方法是实现自定义UIWindow并覆盖
windowLevel
接收器:

@interface TopWindow : UIWindow @end

@implementation TopWindow
- (UIWindowLevel) windowLevel {
    return 20000000.000;
}
@end

// usage:
UIWindow* w = [[TopWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
w.rootViewController = [UIViewController new];
w.hidden = NO;

[w.rootViewController presentViewController:yourActionSheetController animated:YES completion:nil];

这种方法应该是向后兼容的,但尚未测试所有已知版本。快乐的黑客

我什么都试过了,但是这个窗口太高了。@rckones这真的很烦人。如果您运行SDK8应用程序,它的窗口级别较低,因此
UIActionSheet
运行良好。但如果应用程序使用SDK9,它就会飞上天空。这是一个让你使用
UIAlertController
的阴谋<代码>;-)
我甚至在使用
UIAlertController
,但即使这样也不起作用,并且在键盘后面显示得很好:谢谢你,这是一个简单的解决方案,至少在一段时间内很好,直到该值再次改变为止。;)@不幸的是,Travis没有使用私有API。苹果将键盘分为两个窗口,如果不使用调试器或专用API,则无法访问高键盘窗口。这在iOS9中不起作用,它仍将位于键盘后面。虽然这可能是解决问题的一个有价值的提示,但确实需要一个答案来演示解决方案。请提供示例代码来说明您的意思。另一方面,请考虑将此作为注释来写。您肯定关于<代码> UIAlertController <代码>吗?我的应用程序在iOS9中的
UIActionSheet
中遇到了同样的问题,但当我切换到
UIAlertController
时,问题消失了。是的,我确定。但似乎只有当您使用it时,当键盘作为视图的一部分呈现时才会发生这种情况
inputAccessoryView
。这是一种可能的复制方法。我在整个应用程序中使用了很多UIAlertController。所以,我不想在每个处理程序中取消分配。谢谢