如何使用 presentViewController 呈现 iOS 键盘扩展

How to present iOS Keyboard extension using presentViewController

我的目标是在键盘成功实例化时使用方法 presentViewController:animated:completion 呈现 iOS 键盘,利用平滑的向上动画。

一些非常简短的背景:键盘扩展项目是用 Objective-C 编写的,KeyboardViewController.h/.m 处理来自 inputView.xib 的逻辑和一些基本视图布局。

基于此 SO question,建议的几个答案使用从 [UIApplication sharedApplication].keyWindow.rootViewController 调用 presentViewController 的方法。问题是,由于这是一个 iOS 扩展,当我尝试复制此方法时,我收到 sharedApplication 不可用的错误。我想知道是否存在一种变通方法,我可以通过方法 presentViewController 以某种方式通过自身或通过 super 来呈现键盘?在我目前的尝试中,调用 [self presentViewController: self...] 会导致异常。

非常感谢!

做不到。

实际上可以很容易地获得对 [UIApplication sharedApplication] 的引用,最直接的(尽管可能会让您在 App Store 审核中被拒绝)是:

  Class appClass = NSClassFromString(@"UIApplication");
  id app = [appClass performSelector:@selector(sharedApplication)];

运行 在 iPhone 5 模拟器上,[app keyWindow] returns nil 从主输入视图控制器的 viewDidAppear: 方法调用时。

[UIApplication windows],然而,没有,所以我们可以试试

[[[app windows].firstObject rootViewController] presentViewController:self
                                                                   animated:YES
                                                                 completion:nil];

...但它只是抛出一个异常:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller .'

UIApplication windows] 开始遍历视图层次结构揭示了一个有趣的事实:我们的 UIInputViewController 的 window 不在这个 window 层次结构中self.view.window returns 一个单独的 _UIHostedWindow 没有 superView.

此外,从 [UIApplication sharedApplication] 返回的 windows 内存中的地址在应用程序之间没有变化。

结论:我们从sharedApplication得到的UIApplication是我们进程的,不是宿主进程的。因此,在视图和它拥有的 windows 上呈现是没有意义的,因为它的视图对用户不可见。