已接管 PDRCore.rootViewEdgeInsets
windows=1 key=UIWindow insets=48.0/0.0/34.0/0.0 window=48.0/0.0/34.0/0.0 rootView=48.0/0.0/34.0/0.0 statusBar=48.0
[17:07:57.388] webview[#1] {"url":"file:///.../__uniappview.html","before":0,"after":48,"windowTop":"0px","envTop":48,"statusBarTop":0,"headerTop":48,"innerHeight":896,"systemInfo":{"platform":"ios","pixelRatio":2,"windowWidth":414}}
[17:07:58.387] webview[#2] {"url":"file:///.../__uniappview.html","before":48,"after":48,"windowTop":"0px","envTop":48,"statusBarTop":0,"headerTop":48,"innerHeight":896,"systemInfo":{"platform":"ios","pixelRatio":2,"windowWidth":414}} - 发布:2026-11-03 18:18
- 更新:2026-11-03 18:37
- 阅读:106
【报Bug】iOS 27 + UIScene 环境下 uni小程序SDK 的 statusbarHeight/--window-top 为 0,页面顶部顶到状态栏
产品分类: uni小程序SDK
手机系统: iOS
手机系统版本号: iOS 26
手机厂商: 苹果
手机机型: iPhone 11(iPhone12,1),iOS 27.2(24B119)
页面类型: vue
SDK版本号: 5.15(liblibPDRCore 内部版本串 1.9.9.81691)
示例代码:
操作步骤:
- 使用 Xcode 27.1 打包已迁移 UIScene(UIApplicationSceneManifest)的宿主 App,集成 uni小程序SDK 5.15;
- 在 iOS 27.2 真机上安装并启动;
- 打开使用 uni 默认导航栏、依赖状态栏高度的小程序页面(本次为业务小程序「养殖生产」首页);
- 读取页面内 --window-top / --status-bar-height / statusbarHeight,观察页面顶部布局。
- 使用 Xcode 27.1 打包已迁移 UIScene(UIApplicationSceneManifest)的宿主 App,集成 uni小程序SDK 5.15;
- 在 iOS 27.2 真机上安装并启动;
- 打开使用 uni 默认导航栏、依赖状态栏高度的小程序页面(本次为业务小程序「养殖生产」首页);
- 读取页面内 --window-top / --status-bar-height / statusbarHeight,观察页面顶部布局。
预期结果:
页面拿到的 statusbarHeight / --window-top / --status-bar-height 应为 48,与 env(safe-area-inset-top) 一致,默认导航栏自动下移,业务页面无需自行纠偏。
页面拿到的 statusbarHeight / --window-top / --status-bar-height 应为 48,与 env(safe-area-inset-top) 一致,默认导航栏自动下移,业务页面无需自行纠偏。
实际结果:
- statusbarHeight = 0
- --window-top = 0px,--status-bar-height = 0
- header.top = 0,内容顶到状态栏/灵动岛下方
- 同页 env(safe-area-inset-top) = 48、宿主 safeAreaInsets top = 48,均正常
- statusbarHeight = 0
- --window-top = 0px,--status-bar-height = 0
- header.top = 0,内容顶到状态栏/灵动岛下方
- 同页 env(safe-area-inset-top) = 48、宿主 safeAreaInsets top = 48,均正常
bug描述:
问题概述
宿主 App 已按 iOS 26/27 要求迁移到 UIScene 生命周期(Info.plist 配置 UIApplicationSceneManifest / UIWindowScene)。升级到 iOS 27 后,uni 小程序(UniMP)页面拿到的状态栏高度为 0,页面顶部内容直接顶到灵动岛/状态栏区域。
同一时刻 WebView 内的 env(safe-area-inset-top) 为 48(正确),说明 WebView 是全屏容器、系统安全区正常;问题出在 SDK 计算并向页面下发状态栏高度的环节。
受影响范围:依赖 SDK 下发状态栏高度的页面(uni 默认导航栏 / --window-top / --status-bar-height)。自绘导航或不依赖该变量的页面显示正常。
环境
- 设备:iPhone 11(iPhone12,1)真机,iOS 27.2(24B119)
- 打包:Xcode 27.1(Build 27A9275),SDK iphoneos27.1
- uni小程序SDK:iOS 5.15(liblibPDRCore.a 内部版本串 1.9.9.81691)
- 宿主:Flutter 3.41.9 原生壳,CocoaPods 集成,Deployment Target iOS 15.0
- 备注:表单「手机OS系统版本」下拉最高只到 iOS 26,实际测试机为 iOS 27.2
- 对比:同一份小程序代码,在未迁移 UIScene 的旧工程 + iOS 26 及以下显示正常
关键证据(真机日志)
已接管 PDRCore.rootViewEdgeInsets
windows=1 key=UIWindow insets=48.0/0.0/34.0/0.0 window=48.0/0.0/34.0/0.0 rootView=48.0/0.0/34.0/0.0 statusBar=48.0
[17:07:57.388] webview[#1] {"url":"file:///.../__uniappview.html","before":0,"after":48,"windowTop":"0px","envTop":48,"statusBarTop":0,"headerTop":48,"innerHeight":896,"systemInfo":{"platform":"ios","pixelRatio":2,"windowWidth":414}}
[17:07:58.387] webview[#2] {"url":"file:///.../__uniappview.html","before":48,"after":48,"windowTop":"0px","envTop":48,"statusBarTop":0,"headerTop":48,"innerHeight":896,"systemInfo":{"platform":"ios","pixelRatio":2,"windowWidth":414}}
- 原生层 rootViewEdgeInsets 返回 48/0/34/0,宿主传入的安全区正确;
- SDK 下发给页面的 --window-top / statusbarHeight 仍为 0;
- WebView 为全屏(env 取到 48),只能由 SDK 把 48 写进 statusbarHeight;
- 页面内把 --status-bar-height 从 0 纠正为 48 后,header.top 从 0 变为 48,确认变量链路即根因。
初步定位
怀疑 SDK 内部获取窗口/状态栏高度时仍走 UIApplication.keyWindow / AppDelegate.window 等旧路径,在 UIScene 生命周期下取到 nil 或非 key window,最终返回 0。涉及类(静态库符号):PDRCore、PDRCoreAppWindow、PTUserAgentUtil、H5CoreConfig。
已排除
- 不是宿主未传安全区:rootViewEdgeInsets 已确认 48/0/34/0。
- 不是 WebView 非全屏:同页 env(safe-area-inset-top)=48。
- 不是 SDK 版本旧:逐目标文件对比 5.15 与 5.24 的 liblibPDRCore.a,PDRCore.o / PTUserAgentUtil.o / PDRCoreAppWindow.o 二进制完全一致,仅 H5CoreConfig.o 版本串由 1.9.9.81691 变为 1.9.9.81702;liblibNavigator.a、liblibWeex.a 完全一致。5.24 更新日志中「iOS 支持 UIScene 生命周期规范」属于 uni-app x,不是 UniMP。
临时绕过
宿主侧接管 PDRCore.rootViewEdgeInsets,并向页面注入脚本把 --status-bar-height 从 0 纠正为 48,可把 header.top 从 0 拉回 48;属业务侧兜底,存在首帧跳动。
期望
- 确认该问题是否为已知问题;
- 有修复版本请告知版本号;
- 暂无修复请给出官方推荐的接入方式;
- 需要补充信息或最小复现工程请告知,可随时提供。
附件:真机完整日志、工程 Info.plist(含 UIApplicationSceneManifest)、打包后 Info.plist 与版本对比结论见 zip。
感谢这份反馈,整体质量在 bug 报告中属于较高水平。以下以官方视角对这份反馈进行评审,并给出结论与建议。
一、反馈内容完整性评审
- BUG 标题:清晰明确,直接点出「iOS 27 + UIScene + uni小程序SDK + statusbarHeight/--window-top 为 0」的核心要素,便于快速归类定位。
- BUG 描述:非常详尽。环境信息完整(iPhone 11 / iOS 27.2 / Xcode 27.1 / UniMP SDK 5.15 / Flutter 3.41.9 宿主 / CocoaPods 集成),关键真机日志证据链完整:原生层 rootViewEdgeInsets 为 48/0/34/0(宿主传入正确)→ WebView 全屏(env(safe-area-inset-top)=48)→ SDK 下发的 statusbarHeight 仍为 0 → 页面内纠正变量后 header.top 恢复 48,确认变量链路即根因。同时主动排除了「宿主未传安全区」「WebView 非全屏」「SDK 版本旧」三种可能,并做了 5.15 与 5.24 的目标文件级二进制对比,这部分排查工作值得肯定。
- 代码示例:目前提供的是日志输出与变量取值,不是可直接运行的最小复现工程。复现依赖你的宿主工程(Flutter 壳 + UIApplicationSceneManifest 配置 + UniMP SDK 集成),官方侧无法仅凭日志与步骤直接复现。你已表示可随时提供最小复现工程,建议后续提供一个仅包含「UIScene 生命周期 + UniMP SDK 集成 + 一个使用默认导航栏页面」的最小宿主工程,便于工程师直接验证。
- 复现步骤:步骤描述清晰、顺序合理,但同样依赖上述宿主工程,配合最小复现工程即可复现。
- 预期结果:合理。按官方文档,App 端
--status-bar-height应为手机实际状态栏高度(参考 CSS 变量),你预期 statusbarHeight/--window-top 应为 48 并与 env(safe-area-inset-top) 一致,符合文档定义。 - 实际结果:明确具体(statusbarHeight=0、--window-top=0px、header.top=0),与现象直接对应,不构成误报。
- 分类信息:基本完整(平台、厂商、机型、系统版本均给出)。两点小提示:①「手机OS系统版本」填写的是 iOS 26,实际为 iOS 27.2,你已在备注中说明表单限制,可以接受;②问题分类为「其他」,建议后续选择更贴近 uni小程序SDK/原生集成的分类,便于流转。
另外说明:我无法识别附件内容,你在正文中已将关键日志与结论以文本形式贴出,这一点做得很好;后续如需补充信息,请继续以文本形式直接写在正文中。
二、Bug 是否成立的分析
结合官方已有结论,该现象成立,但需说明其性质:
- UniMPSDK 目前不支持 UIScene 场景。官方此前在「iOS26 系统下 UniMP 内部使用 UIAlertView 发生崩溃」的反馈中已明确回复:UniMPSDK 不支持 UIScene 的场景,将工程改成之前的 AppDelegate 即可。
- 关于 UIScene 适配的官方口径:uni-app x 即将于下个版本 5.21 支持 UIScene;目前 uni-app(含 UniMP SDK)还没有排期。你在「已排除」中判断「5.24 更新日志中『iOS 支持 UIScene 生命周期规范』属于 uni-app x,不是 UniMP」,这一判断与官方口径一致。
- 社区侧,2026 年 4 月也有开发者提问「什么时候适配基于 UIScene 场景的生命周期」,目前尚无官方回复,也没有明确的适配时间节点。
因此结论是:你遇到的 statusbarHeight/--window-top 为 0,属于 UniMPSDK 未适配 UIScene 生命周期这一已知限制在 iOS 27 + UIScene 宿主下的具体表现,你的初步定位方向(SDK 在 UIScene 环境下取窗口/状态栏高度失败)与官方口径吻合。现象真实、反馈有效,但它不是一个新的独立缺陷,而是上述已知限制的又一表现。
三、针对你四点期望的回复
- 是否为已知问题:是。UniMPSDK 不支持 UIScene 场景为官方已确认的限制。
- 修复版本:目前没有 UniMP SDK 适配 UIScene 的版本排期信息可以提供。uni-app x 自 5.21 起支持 UIScene,但不适用于 UniMP SDK,请勿以该版本号作为 UniMP 的修复预期。
- 官方推荐接入方式:在 UniMP SDK 完成 UIScene 适配之前,官方推荐将宿主工程改回传统的 AppDelegate 生命周期(不启用 UIApplicationSceneManifest/UIScene),这与你在「未迁移 UIScene 的旧工程 + iOS 26 及以下显示正常」的观察一致。你当前的临时绕过(接管 PDRCore.rootViewEdgeInsets + 注入脚本纠正 --status-bar-height)属于业务侧兜底,存在首帧跳动等风险,不建议作为长期方案。
- 补充信息:如工程师需要进一步确认,可按上文第 3 点提供最小复现工程(以文本形式描述关键配置即可)。
如需进一步沟通,欢迎到专业群(uni-app 官方技术交流群 1)咨询,群中有相关专业的管理员和群友。
Gavyn (作者)
感谢确认。补充一个关键前提,希望官方在给结论时一并考虑:
「改回 AppDelegate」在 Xcode 26/27 工具链下已不可行
- Apple 自 iOS 26 SDK 起强制要求 App 采用 UIScene 生命周期:用 iphoneos26+ SDK 链接、且 Info.plist 不含 UIApplicationSceneManifest 的 App,在 iOS 26+ 设备上会直接启动失败(系统要求 UIScene lifecycle)。
- 我们的包正是用 Xcode 27.1 / iphoneos27.1 构建,去掉 SceneManifest 后无法启动,也无法上架。也就是说,「回退 AppDelegate」只适用于仍在用 Xcode 25 及以下、iOS 25 SDK 构建的工程;对已经要适配 iOS 27 的项目没有可操作性。
因此希望能得到一个 UIScene 下的过渡方案,以下任选其一即可:
- 提供一个宿主可调用的 API/属性,显式指定小程序页面的状态栏高度(例如 PDRCore 层设置 statusBarHeight,或让已经接管的 rootViewEdgeInsets 真正参与 --window-top / statusbarHeight 计算);
- SDK 内部把窗口获取改为遍历 connectedScenes,取 activationState == .foregroundActive 的 windowScene,再用 scene.keyWindow / scene.windows.first 的 safeAreaInsets.top 作为状态栏高度;
- 若短期无法修复,请给一个官方认可的宿主侧兜底写法。我们目前是接管 rootViewEdgeInsets + 注入脚本纠正 --status-bar-height,会有首帧跳动,不适合长期。
另外想确认两点:
- UniMP 是否有内部 issue 或排期可以跟踪 UIScene 适配进度?
- 在适配完成前,官方是否接受「保留 UIScene + 宿主侧兜底」作为过渡方案?
我们也可以随时提供最小复现工程(UIScene 宿主 + UniMP SDK + 一个使用默认导航栏的页面),需要的话请告知。