AppleEvent

2026 iOS 27 窗口适配:别等折叠 iPhone 的验收清单

2026 iOS 27 窗口适配:别等折叠 iPhone 的验收清单

截至 2026 年 8 月 23 日,采用最新 SDK 构建的应用如果没有采用 UIScene 生命周期,可能无法启动;同时,iOS 27 下的 iPhone 应用已经需要面对 iPhone Mirroring 和 iPad 上的可调整窗口行为。官方 Session 278 文字稿 已明确这一变化。

获胜者是“现在就按可用 scene 空间改造”,适用条件是所有准备使用 Xcode 27 构建或验收的 iOS 团队。 不要等待折叠 iPhone 的名称和尺寸官宣。今天应先迁移 scene 生命周期,清理 UIScreen.main、设备类型和方向判断,再用 Xcode 27 建立连续尺寸验收。折叠屏传闻只影响未来新增的测试点,不影响当前改造。

这篇文章适合三类人:

  • 仍维护大量 UIKit 旧代码、固定屏幕尺寸或方向判断的开发者。
  • 需要为 iPhone Mirroring、iPad 及未来新形态窗口建立回归矩阵的 QA 团队。
  • 正在评估本地 Mac 是否足以支撑 Xcode 27、多实例模拟器和临时扩容的技术负责人。

iOS 27 窗口适配:先改依据,再谈折叠屏

这次变化最容易被误读成“Apple 提前为折叠 iPhone 做准备”。更准确的判断是:系统先把窗口变化暴露给现有设备和测试环境,开发团队必须让应用能够根据运行时可用空间变化。

官方说明确认,iOS 27 和 macOS 27 下,iPhone Mirroring 窗口可以自由调整;iPhone-only 应用运行在 iPad 上时,也会进入可调整尺寸的环境。应用需要在运行时根据 scene 的可用尺寸动态布局,而不是把“设备型号”当成固定画布。相关技术说明 已将需要审计的重点归纳为 scene 生命周期、主屏幕引用、用户界面类型和界面方向。

因此,团队应把问题分成三层:

  • 强制迁移: 使用 scene 生命周期。官方发布说明指出,采用最新 SDK 构建时,未迁移的应用可能无法启动。scene 配置文档
  • 优先改造: 删除依赖 UIScreen.main、固定 screen.boundsuserInterfaceIdiominterfaceOrientation 的布局逻辑。
  • 未来补充: 等折叠设备正式公布后,再把已确认的屏幕形态加入回归矩阵。名称、内外屏尺寸、价格和上市安排目前不能作为设计依据;媒体报道只能作为预研线索。相关报道

固定尺寸的隐性成本不只是一处约束失效。窗口缩小时,导航栏可能挤压内容,弹窗锚点可能跑出可视区域,列表单元格可能因文本换行而变高。窗口切换场景后,旧缓存还可能继续使用原来的尺寸,最终表现为裁切、黑边、模糊或交互区域偏移。

⚠️ 经验提醒:UIScreen.main 不是“突然被删除”的 API。真正的问题是,它代表设备的主屏幕,不一定代表当前 scene 所在的屏幕。应用能编译,不等于它拿到的是正确布局信息。

开发者对照:旧 API 清理与可验证替代方向

UIKit 旧项目:先扫描四类调用

第一步不是批量替换,而是建立代码记录。建议在项目根目录执行搜索,分别登记调用位置、用途、影响页面和负责人:

rg "UIScreen\.main|screen\.bounds|userInterfaceIdiom|interfaceOrientation" .
rg "applicationDidBecomeActive|applicationWillResignActive|applicationDidEnterBackground" .

扫描结果可以按以下方式处理。

1.UIScreen.mainscreen.bounds

旧写法常见于启动页、图片裁切、弹窗尺寸和自绘视图:

let width = UIScreen.main.bounds.width
let scale = UIScreen.main.scale

如果方法属于某个视图或控制器,应优先改为:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let availableSize = view.bounds.size
    let scale = traitCollection.displayScale
    updateLayout(for: availableSize, scale: scale)
}

如果业务确实需要屏幕对象,则从当前窗口所属 scene 获取:

let screen = view.window?.windowScene?.screen

官方文档明确建议从上下文获得对应 screen,并使用 traitCollection.displayScale 代替直接读取屏幕缩放。UIScreen.main 说明UIWindowScene.screen 文档 都给出了这一方向。

2.userInterfaceIdiom

旧逻辑经常写成:

if traitCollection.userInterfaceIdiom == .pad {
    showSidebar()
}

在可调整窗口环境中,iPhone 应用运行在 iPad 上仍可能保持 phone idiom。于是设备类型无法回答“当前空间是否足够”。

替代方式应围绕 size class 或实际可用宽度:

if traitCollection.horizontalSizeClass == .regular {
    showSidebar()
} else {
    showTabBar()
}

如果页面结构对宽度特别敏感,直接读取当前容器的 view.bounds.width,不要把 .regular 当成唯一判断条件。

3.interfaceOrientation

方向可以是系统偏好,却不再适合承担布局职责。尤其在 iPhone Mirroring 中,窗口外观比例可能变化,但应用内部的方向报告并不等于“当前窗口是横向画布”。

方向判断应改为:

  • 通过 size class 决定单栏、双栏或折叠导航。
  • 通过 view.bounds 决定卡片列数、视频画布和工具栏位置。
  • 只有驾驶、游戏等确实需要锁定方向的功能,才使用方向锁定偏好。

4.旧 App 生命周期

如果状态保存、网络暂停、计时器暂停仍写在 UIApplicationDelegate 的全局回调中,需要按 scene 拆分。一个应用可能同时拥有多个 UI scene,每个 scene 都有独立状态和前后台变化。迁移指南

完成后,开发验收不能只看“搜索结果归零”。每个替换点都要绑定一个现象:

  • 窗口缩放后,标题和按钮仍在安全区域内。
  • scene 重新连接后,导航路径和筛选状态保持正确。
  • 进入后台再回来时,缓存尺寸与当前窗口一致。
  • 从 iPhone Mirroring 切换到另一种窗口状态后,不出现旧画布残留。

SwiftUI、混合架构与专项组件:按空间连续变化验收

SwiftUI 项目通常不会直接出现大量 UIScreen.main,但固定宽度问题仍然存在。重点检查 GeometryReader 外部是否传入了预设宽度,UIViewControllerRepresentable 是否把 UIKit 层计算出的设备尺寸传给 SwiftUI,以及 AnyView 分支是否根据设备类型直接切换整套页面。

常见风险包括:

  • 用“iPhone 页面”和“iPad 页面”两套视图代替连续布局。
  • 通过方向判断强制切换导航结构。
  • 弹窗内容设置固定宽高,窗口变窄后按钮不可达。
  • 混合架构中,UIKit 包装层只在初始化时传递尺寸,后续 scene 变化不再更新。
  • 列表、表单和多栏页面只测试几个传统设备规格,未测试中间宽度。

混合项目应增加一个明确的尺寸传递路径。UIKit 容器负责提供当前可用空间,SwiftUI 视图根据环境变化刷新,而不是把设备型号作为业务状态传入。对于导航结构,验收重点是“内容是否仍然可达”,而不是“页面是否仍然看起来像原来的 iPhone 截图”。

游戏、地图、视频和 Metal 自绘界面需要单独分组。它们通常同时依赖:

  • 渲染目标尺寸。
  • 触控或手势坐标转换。
  • 纹理与缓存尺寸。
  • 内容宽高比。
  • 安全区域和裁切策略。

窗口调整时,如果只更新 UIKit 控件而没有同步更新渲染目标,常见结果是画面模糊、内容被裁切、出现黑边,或者触控位置与视觉位置不一致。地图还要检查投影区域和标注布局是否同步刷新;视频则要确认播放器容器、字幕和控制条不会被窗口边缘截断。

对于高成本资源,不要在连续拖动的每个中间状态都重建全部缓存。官方示例提供了 isInteractivelyResizing 的判断思路:调整过程中可以延迟高成本资源更新,在交互结束后再提交最终尺寸。UIKit 灵活布局示例

这里不能从“界面看起来卡”推导具体帧率,也不能把一次模拟器表现写成普遍性能结论。性能验收应记录构建版本、设备或模拟器环境、窗口状态、复现步骤和 Instruments 证据;没有官方说明或本站实测,就不要写具体数值。

QA 对照:设备规格测试升级为窗口状态测试

QA 团队的核心变化,是把“测哪台设备”改成“测哪种窗口状态”。Xcode 27 的 Device Hub 可以进入 resize mode,通过拖动边缘或输入尺寸测试任意窗口状态,不必为每一个尺寸单独准备模拟器。调整模拟设备尺寸文档

建议建立以下验收入口:

  • Device Hub: 适合快速连续拖动、极窄和极宽窗口测试。
  • Xcode Previews: 适合组件级检查,重点看文本、表单、导航栏和弹窗。
  • iPhone Mirroring: 用真实设备验证窗口行为、输入链路和实际应用状态。
  • 真实 iPad: 验证 iPhone-only 应用在 iPad 上的窗口变化、方向和交互。
  • 自动化 UI 测试: 验证前后台切换、scene 重连和关键流程是否因尺寸变化丢失状态。

Xcode 27 的测试工具也有边界。官方发行说明提示,Device Hub 的某些输入行为属于主机端模拟,并不完全等同于真实设备上的指针交互;并行测试时,设备可能不会持续显示在 Device Hub 中,但测试仍可能在后台运行。Xcode 27 发行说明

第二步:使用这份发布前勾选清单

  • [ ] 项目已采用 UISceneDelegate,并能解释每个 scene 的连接、进入后台和重连行为。
  • [ ] 全仓库已扫描 UIScreen.mainscreen.boundsuserInterfaceIdiominterfaceOrientation
  • [ ] 每个遗留调用都有替代依据,而不是只做语法替换。
  • [ ] UIKit 页面在窗口连续缩放中不会出现约束冲突或内容溢出。
  • [ ] SwiftUI 包装层会在容器尺寸变化后重新传递可用空间。
  • [ ] 导航、弹窗、表单、列表和多栏页面均测试了极窄与极宽状态。
  • [ ] 动态文字放大后,主要操作仍然可见且可点击。
  • [ ] iPhone Mirroring 调整窗口后,按钮、弹窗锚点和触控坐标保持一致。
  • [ ] iPad 上的 iPhone-only 页面不会因为设备类型判断而显示错误布局。
  • [ ] 游戏、地图、视频和 Metal 组件会同步更新渲染尺寸、缓存和坐标转换。
  • [ ] 连续拖动结束后,最终尺寸会触发一次完整资源更新。
  • [ ] 前后台切换、scene 重连和状态恢复均有截图或日志证据。
  • [ ] 每条缺陷记录包含环境、窗口状态、复现步骤、预期结果和截图。
  • [ ] 所有未解决项都有负责人、风险级别和发布决策。

如果测试仍只写“iPhone 规格 A 通过、iPad 规格 B 通过”,验收信息是不完整的。窗口状态、动态文字和 scene 生命周期才是这次改造真正要锁定的变量。

技术负责人对照:继续占用本地 Mac,还是临时增加远程环境

技术负责人不应一开始就购买或租赁固定配置。先根据代码扫描结果分组:

可自动替换: 明确的 UIScreen.main、屏幕缩放读取和简单方向分支。适合批量修改后由开发者自测。

需要人工重构: 依赖设备类型切换整套页面、混合架构尺寸传递、弹窗和多栏导航。需要开发、设计和 QA 共同确认。

必须专项回归: Metal、地图、视频、复杂 Canvas、缓存和触控坐标。应安排独立环境和完整证据记录。

本地 Mac 更适合长期稳定开发、需要物理接口、需要频繁连接真机,或者团队并发很低的项目。但当多个开发者和 QA 同时需要不同 Xcode 27 环境时,个人开发机容易出现三个问题:

  • 构建任务互相抢占,提交验证排队。
  • 模拟器状态互相污染,问题难以复现。
  • 团队成员的 SDK、依赖和系统版本不一致,截图无法直接比较。

临时增加云端 Mac 测试环境,更适合短期兼容性回归、发布前集中验收、远程协作或需要并行运行多个模拟器的团队。代价也很明确:远程连接受网络质量影响,真机能力和物理接口不一定等同于本地,长期高负载使用还需要重新比较总成本。

在决定前,负责人至少应算清四项:

  • 同时需要构建的分支数量。
  • 同时运行的模拟器或真实设备验证数量。
  • 每轮回归持续多久。
  • QA 是否需要远程共享窗口、日志和截图。

如果只是单人开发,继续使用本地 Mac 通常更直接;如果是发布前的短周期并行验收,则临时扩容往往比让所有人排队等待更容易控制交付风险。需要核对远程环境登录、权限和交付方式时,可先查看 ProxyMac 的使用帮助;需要比较短期使用方案,再根据团队人数和测试周期查看 ProxyMac 的方案页面

最终发布签字清单至少要包含:代码扫描结果、测试环境、窗口状态、失败条件、截图证据、负责人和未解决项。折叠 iPhone 正式公布后,只需在这套矩阵中增加确认过的尺寸与比例,不必重新设计整套布局架构。

FAQ:开发与 QA 最容易卡住的五个判断

UIScreen.main 在 iOS 27 还能继续使用吗?

它不是简单地从 SDK 中消失,但已经不适合作为当前窗口的布局依据。可通过窗口所属的 UIWindowScene 获取对应 screen;读取缩放时优先使用 traitCollection.displayScale,计算布局时直接使用 view 或 superview 的可用尺寸。

Xcode 27 怎样测试可以自由调整大小的 iPhone 窗口?

先在 Device Hub 或 Xcode Previews 中运行采用 iOS 27 SDK 构建的应用,再进入 resize mode,拖动设备顶部、底部或侧边的控制点,也可以输入尺寸。连续拖动用于发现布局抖动,极窄和极宽状态用于验收边界。

iPhone Mirroring 调整窗口后界面变形,应该从哪里修复?

先检查是否依赖 UIScreen.main、固定 screen bounds、userInterfaceIdiominterfaceOrientation。随后把布局条件改为 size class、trait collection 和当前 view.bounds,并确认缓存、触控坐标、弹窗锚点会在 scene 尺寸变化后重新计算。

折叠 iPhone 发布前,哪些布局 API 应该先完成迁移?

优先处理 scene 生命周期、主屏幕引用、设备类型判断、方向判断和固定画布宽高。折叠 iPhone 的名称、内外屏尺寸和价格尚未官宣,不能据此设计断点;这些参数只应在正式确认后补充为测试样本。

iOS 27 应用窗口适配完成后,怎样才算真正验收通过?

验收记录不能只写设备型号。每条用例都应写明构建环境、窗口状态、复现步骤和截图,并覆盖连续拖动、极窄、极宽、动态文字、横竖比例变化、前后台切换及 scene 重连;出现溢出、控件不可达、缓存不刷新或状态丢失即不通过。

最后的环境选择应建立在代码审计和并行测试量之上。继续占用个人 Mac 的缺点是并发能力受限、环境难以隔离、远程验收不方便;临时云端 Mac 的缺点则是网络依赖、真机与物理接口能力有限、短租周期需要提前规划。若团队只是临时完成 Xcode 27 兼容性回归,ProxyMac 的 Mac 环境更适合按人数、模拟器数量和测试周期灵活扩容;若项目是长期稳定重负载开发,或必须连接专用硬件,则应优先保留本地 Mac。

立即开通云端 Mac,开始窗口适配回归

ProxyMac 提供独享 M4 云端 Mac,适合开发、调试与连续尺寸回归测试。
支持浏览器、SSH 和 VNC 多种方式远程接入,团队成员可快速进入统一开发环境。