跟上键盘的节奏:iOS 17 键盘架构重构与适配
Keep up with the keyboard
2023年6月5日
一句话判断
iOS 17 把键盘搬到了独立进程,配合 Stage Manager 和硬件键盘场景的增多,是时候用 Keyboard Layout Guide 重新审视你的布局逻辑了。
这场 Session 讲了什么
这场 Session 核心讲了三件事:
进程外键盘(Out-of-Process Keyboard)。iOS 17 中,键盘的视图和逻辑从 App 进程中独立出来了。这样做的好处是安全性和隐私——App 无法直接接触键盘进程中的用户输入;内存方面也更高效,整个系统只需要一个键盘实例,而不是每个 App 各一份。对于大多数 App 来说这个变化是透明的,但如果你的代码对文本输入、选择变化的时序特别敏感,需要注意新的异步行为。
多场景键盘适配。在全屏模式下,键盘适配很简单——把视图上移键盘高度就行。但 Stage Manager 打破了这个假设:App 可能不是全屏的,键盘场景和 App 场景不再对齐。你需要的是键盘和 App 窗口的交集高度,而不是键盘的完整高度。更复杂的是,多个窗口可能同时存在,每个都需要独立的适配计算。
UIKeyboardLayoutGuide 的增强。iOS 15 引入的 Keyboard Layout Guide 在 iOS 17 中获得了三个新的自定义属性:followsUndockedKeyboard 控制是否跟踪浮动键盘、usesBottomSafeArea 控制键盘收起时的底部行为、以及与 InputAccessoryView 的协作方式。这些属性让一行约束就能处理以前需要大量手动计算的场景。
值得深挖的点
异步时序变化的影响。之前键盘初始化是同步的,调用 becomeFirstResponder 后键盘 UI 立刻就位。现在键盘进程异步初始化,中间有个时间差。如果你的 App 在文本输入的时序上做了假设(比如在键盘弹出后立刻读取某个输入状态),可能会遇到竞态问题。
硬件键盘的两种工具栏形态。全尺寸工具栏算作键盘的一部分,视图应该避开它;而迷你工具栏在非 Stage Manager 模式下不算键盘的一部分,会覆盖在内容上方,用户可以拖动它来查看被遮住的内容。但在 Stage Manager 下,迷你工具栏又算作键盘的一部分。这套逻辑如果不了解,很容易写出错误的布局代码。
一行约束替代一堆计算。UIKeyboardLayoutGuide 的设计哲学是”系统帮你算好,你只要约束就行”。配合新属性,以前需要监听键盘通知、手动计算高度、处理浮动键盘等各种分支逻辑,现在可以简化为一到两个约束。
代码片段
// 最简单的键盘适配:一行约束
let keyboardGuide = view.keyboardLayoutGuide
// 让你的内容视图底部等于键盘布局指南的顶部
contentView.bottomAnchor.constraint(
equalTo: keyboardGuide.topAnchor
).isActive = true
// iOS 17 新增属性配置
let guide = view.keyboardLayoutGuide
// 跟踪浮动键盘(iPad 上键盘可以拖动到任意位置)
guide.followsUndockedKeyboard = true
// 键盘收起时跟踪屏幕底部而非安全区域
// 效果类似 InputAccessoryView 的行为
guide.usesBottomSafeArea = false
最佳实践
- 优先使用
UIKeyboardLayoutGuide而不是手动监听键盘通知。Messages 和 Spotlight 都已经迁移到这个方案。 - 如果你的 App 支持 Stage Manager,一定要测试多窗口场景下的键盘行为。
- 注意
viewWillAppear中 trait collection 可能不是最新的,iOS 17 新增的viewIsAppearing是更安全的时机。 - 浮动键盘和迷你工具栏的行为在不同模式下有差异,写布局代码前先理清场景。
还有什么值得关注
viewIsAppearing回调向后兼容到 iOS 13,不需要做版本判断- Session 提到 Spotlight 和 Messages 等 Apple 自家复杂 App 已经在用 Keyboard Layout Guide
- 新架构为未来的键盘功能奠定了基础,值得持续关注后续变化
- 如果你有自定义 InputAccessoryView,需要重新审视它在各种键盘场景下的表现