自定义键盘拓展(iOS Custom Keyboard Extension)不断变高问题解决

最近几个用户给我反馈说打开复制板 (opens new window)键盘拓展后,每次切出应用再切回来,键盘高度都会变高一些,我在我的 iPhone12 iOS17 上试了试确实如此。

在网上搜了一下之后,发现也有相关的反馈,

  1. Custom Keyboard Extension Keeps Increasing In Height (opens new window)
  2. iOS custom keyboard height increases on every switch (opens new window)

但是并没有人给出合适的解决方案,倒是推荐用 SwiftUI 去重新实现一下,我还不想重写,所以想着有没有什么办法在当前方案上解决这个问题。

# 当前方案介绍

基本思路是使用 iOS 提供的自定义键盘拓展方式,这也是在 iOS 上实现跨应用自定义键盘的唯一方式。官方文档 Creating a custom keyboard (opens new window)

具体来说是通过继承系统提供的 UIInputViewController 类来提供键盘交互界面,然后在自定义的键盘交互界面里进行布局。键盘拓展的数据和主应用的数据是可以共享的,配置 AppGroup 就能实现。而具体的对输入框中文字操作的方法是通过 UIInputViewControllertextDocumentProxy 实例来进行。

Untitled

# 解决思路

回到这里的问题,键盘高度是如何控制的?官方文档 Configuring a custom keyboard interface (opens new window) 也有相关介绍如下,里面提到的关于自定义键盘的高度可以通过向 UIInputViewController 的 view 属性添加自动约束布局(AutoLayout)的方式来实现。

By default, iOS sizes custom keyboards to match the system keyboard according to screen size and device orientation. A custom keyboard’s width is always set by the system, typically matching the screen width. You can adjust the height of your custom keyboard’s primary view using Auto Layout. To change a keyboard’s height, adjust the height constraints on the UIInputViewController’s view to achieve the desired height for your interface.

在官方的这篇 App Extension Programming Guide → Custom Keyboard (opens new window) 文档里甚至给出了具体的代码实现

CGFloat _expandedHeight = 500;
NSLayoutConstraint *_heightConstraint = 
    [NSLayoutConstraint constraintWithItem: self.view 
                                 attribute: NSLayoutAttributeHeight 
                                 relatedBy: NSLayoutRelationEqual 
                                    toItem: nil 
                                 attribute: NSLayoutAttributeNotAnAttribute 
                                multiplier: 0.0 
                                  constant: _expandedHeight];
[self.view addConstraint: _heightConstraint];

不过我在工程中设置了类似的代码也没有阻止键盘越变越高。

PS: 我在调试键盘拓展的时候,总是没办法 attach 到键盘拓展的 process,报错 → Could not attach to pid: "xxx", attach failed (Not allowed to attach to process. Look in the console messages (Console.app), near the debugserver entries, when the attach failed. The subsystem that denied the attach permission will likely have logged an informative message about why it was denied.) 在公司改了好久都不行,回家之后用家里的电脑调试同样的工程就能正常 attach process… 服了..

为了排除别的可能得问题,我新建了一个空的自定义键盘拓展工程去调试,发现空的键盘拓展也是会出现键盘高度越变越高的问题… 感觉是苹果的系统出问题了..

不过还是不死心,我之前设置的视图高度约束是放在 UIViewControllerviewDidLoad 方法中的,UIViewController 还有一个 updateViewConstraints 方法,这个方法的执行时机是视图控制器的视图需要更新约束的时候,应该是在布局相关的方法执行之前执行。

所以我把约束的代码调整到这个方法里,重新调试发现问题解决了。

override func updateViewConstraints() {
    let desiredHeight:CGFloat = 305
    let heightContraint = NSLayoutConstraint(
        item: view!,
        attribute: .height,
        relatedBy: .equal,
        toItem: nil,
        attribute: .notAnAttribute,
        multiplier: 1.0,
        constant: desiredHeight)
    view.addConstraint(heightContraint)
    super.updateViewConstraints()
}

感觉是系统可能在每次切回应用的时候让视图约束失效导致高度不断变化,目测应该是 iOS 系统更新引起的问题。先就这样吧,以后再遇到问题再说。

参考地址:

  1. UIKit - Creating a custom keyboard (opens new window)
  2. Attach process failed when trying to run intents extension via Xcode (opens new window)
  3. Cannot debug Catalyst App: "Message from debugger: Process attach denied” (opens new window)

关注我的微信公众号,我在上面会分享我的日常所思所想。