iOS 18.6.2 主屏 Web 应用真机实测
发布于 更新于
iOS 18.6.2 上的主屏 Web 应用在实测中拿到了 Safari 的 Cookie 副本,也能处理通知点按。2026-10-20,我们用一台 iPhone 16 Pro(版本号 22G100,Safari 18.6)测了三个小时,逐项检查 11 个问题,当晚又补测了状态栏颜色。多数结果印证了 WebKit 或社区笔记已有的描述,并留下这个版本的测量值;前期检索没有找到另外两项结果的公开记录。
测试涉及应用启动、图标选择、Safari 数据复制、屏幕顶部布局与颜色,还检查了通知权限、推送订阅、notificationclick 和角标是否按文档工作。OpenPWA 的一名操作者把测试页面加到手机主屏幕并打开,还点按了通知、截了图。每完成一步,智能体就用 USB 读取页面状态。脱敏后的证据以 CC BY 4.0 公开在数据包里。
18.6.2 上的实测结果
链接到“18.6.2 上的实测结果”一节没有 manifest 和图标的页面加到主屏幕后,仍在 Safari 中打开,使用 Safari 的存储,没有以 Web 应用运行。一个第一方 Cookie 在每个新主屏应用创建时从 Safari 复制过去一次,之后各自独立;localStorage 与 IndexedDB 都没有复制过去。这在 18.6.2 上重现了 WebKit 对 iOS 17.2 的描述。在已安装应用中,notificationclick 在全部 6 次点按中同时经由 addEventListener 与 onnotificationclick 属性触发,每次都有存活的窗口可以聚焦。'onnotificationclick' in self 在由已安装应用控制的 Service Worker 中为 true,在由 Safari 标签页控制的同一个 worker 中为 false,这可以解释 browser-compat-data(BCD)里的「不支持」记录。在一个从未请求过权限的应用里,权限请求挂起了 2068 ms,直到操作者回应可见的系统提示。Service Worker 作用域为子路径时,注册上已有订阅,window.pushManager.getSubscription() 却返回 null,这与 WebKit「只有根作用域的 worker 与 window 共享订阅」的规则一致。使用默认状态栏样式时,页面上方是一条纯色条带,页面内容始终到不了那里;条带颜色在页面有 theme-color meta 时取自它,否则取自 manifest 的 theme_color。black-translucent 加 viewport-fit=cover 则把页面画到状态栏之下(REPORT.md,openpwa.net)。
主屏应用需要单独测试的意义
链接到“主屏应用需要单独测试的意义”一节自 iOS 16.4 起,站点的 manifest 只要将 display 设为 standalone 或 fullscreen,添加到主屏幕后就会以 Web 应用打开。这样的应用能用 Web Push、通知和 Badging API,Safari 标签页则没有这些能力(Web Push for Web Apps on iOS and iPadOS,webkit.org)。启动方式会影响可用接口、页面读到的存储、屏幕顶部的绘制,以及通知事件能否到达 Service Worker。只在 Safari 标签页里测试或检测特性,就漏掉了已安装应用的运行场景。
两处资料分歧促成了这次测试。BCD 把 ServiceWorkerGlobalScope 上的 notificationclick 记为 iOS 版 Safari 不支持,而一个长期未关闭的 BCD issue 报告该事件在已安装应用中会触发(mdn/browser-compat-data#22959,github.com)。OpenPWA 自己的主屏存储隔离页面曾告诉读者,在 Safari 中写入的登录令牌在已安装应用中不存在,而 WebKit 的 Safari 17.2 文章记载,创建应用时会复制 Cookie(WebKit Features in Safari 17.2,webkit.org)。我们在设备上实测了这两个问题,并据此更正了存储隔离条目。
这次运行也是一份基线。同一台手机之后会升级到 iOS 27,再复查同一批页面;而一旦升级,iOS 18.6.2 的状态就再也测不到了。有一期技术周刊写道,iOS 27 上已安装应用会在状态栏下渲染模糊效果,theme-color 与 apple-mobile-web-app-status-bar-style 在那里都没有作用(So what’s up with the iOS27 blur?,modernwebweekly.substack.com);18.6.2 的测量值可供对照。
已有记录
链接到“已有记录”一节结果注明了哪些印证已有描述,哪些属于新发现。前期检索查阅了 WebKit 的版本文章、BCD 及其 issue 讨论、文中提到的 WebKit 缺陷,以及 Maximiliano Firtman 关于 iOS 上 PWA 支持情况的笔记,笔记更新于 2026-10-13(iOS PWA Compatibility,firt.dev)。
厂商文档
链接到“厂商文档”一节WebKit 以 manifest 定义主屏 Web 应用;没有 manifest、也没有 apple-mobile-web-app-capable meta 标签时,站点会存成书签,在默认浏览器中打开(Web Push for Web Apps on iOS and iPadOS,webkit.org)。自 iOS 26 起,添加到主屏幕的站点默认都以 Web 应用打开,除非用户关闭「Open as Web App」(WebKit Features in Safari 26.0,webkit.org),所以 18.6.2 上的这次运行是 26 之前的对照组。
存储方面,WebKit 的跟踪防护页面写道「the website data of home screen web applications is kept isolated from Safari」(Tracking Prevention in WebKit,webkit.org),WebKit 181849 号缺陷下的回复称这种分隔是「by design」(Bug 181849,bugs.webkit.org)。Safari 17.2 文章为 Cookie 收窄了这条规则:用户点按「添加到主屏幕」创建 Web 应用时,「the cookies are copied over, including the information about login state」,「No other kind of local storage is copied over」,并且「After a user adds a web app to the Home Screen or Dock, no other website data is shared」(WebKit Features in Safari 17.2,webkit.org)。
声明式 Web Push 自 iOS 与 iPadOS 18.4 起加入 window.pushManager,页面无需 Service Worker 即可订阅(WebKit Features in Safari 18.4,webkit.org)。WebKit 介绍它的文章补充:「If you do also have a registered service worker scoped to the root level of your website domain, it shares the same push subscription as the window object」(Meet Declarative Web Push,webkit.org)。
屏幕顶部方面,Apple 已归档的 meta 标签参考写道,取值为 default 或 black 时「the web content is displayed below the status bar」,取值为 black-translucent 时「the web content is displayed on the entire screen, partially obscured by the status bar」(Supported Meta Tags,developer.apple.com)。Safari 15 加入了 theme-color,用来改变「the color of the status bar and overscroll area in Safari on iOS 15」(New WebKit Features in Safari 15,webkit.org)。Web Application Manifest 把 theme_color 定为应用上下文的默认主题色,并允许用户代理用作用域内文档的 theme-color meta 元素覆盖它,但不要求这样做(Web Application Manifest,w3.org)。
兼容性数据与缺陷报告
链接到“兼容性数据与缺陷报告”一节BCD 的 ServiceWorkerGlobalScope.json 把 safari_ios 上的 notificationclick_event 记为 version_added: false(BCD api/ServiceWorkerGlobalScope.json,github.com)。在 2024 年提交、2026-10-20 仍未关闭的 #22959 中,一位 BCD 贡献者解释说,采集器在 Service Worker 中检查 "onnotificationclick" in self,这一检查在 iOS 16、17、18 的 Safari 上都失败,而该属性受一个 WebKit 偏好设置控制;另有参与者报告事件在已安装应用中会触发(mdn/browser-compat-data#22959,github.com)。WebKit 268797 号缺陷「notificationclick events in serviceworkers not firing」仍为 NEW 状态,其中有报告称用户点按通知时如果应用没有存活页面,事件不触发(Bug 268797,bugs.webkit.org)。BCD 把 api.Window.pushManager 记为 iOS 版 Safari 18.4 起支持,附注说通知只在保存到主屏幕的 Web 应用中可用,但没有说明普通标签页中是否暴露该对象(BCD api/Window.json,github.com)。
社区笔记
链接到“社区笔记”一节Firtman 的笔记记载:自 17.2 起登录 Cookie 会复制到已安装应用,存储不与浏览器共享;apple-touch-icon link 元素会覆盖 manifest 中的图标声明;自 iOS 15 起不建议用 apple-mobile-web-app-status-bar-style,改用 theme-color meta 标签;black-translucent 仍是「Still the only way to get a fullscreen app」(iOS PWA Compatibility,firt.dev)。我们在 18.6.2 上测试了其中几项行为。
这次测试补上了什么
链接到“这次测试补上了什么”一节Cookie 复制、notificationclick 在已安装应用中触发、black-translucent 让页面铺满全屏,以及图标与 manifest 的规则,此前都有记录。这次测试补上了具体版本和日期下的测量值。有两项结果在公开资料里没有找到:'onnotificationclick' in self 在由已安装应用控制的 worker 中为 true,在由 Safari 标签页控制的同一个 worker 中为 false;window.pushManager 在普通 Safari 标签页中存在,而那里没有 Notification 与 PushManager。默认状态栏在 18.x 上的几何测量值(下移 62 px、874 CSS px 中占 812、纯色条带)此前也没有公开,尽管它所测的行为是有记录的(FINDINGS.md,openpwa.net)。
判断结果时,我们优先采用页面读数,其次是截图,最后才是口头描述。测试报告逐步给出了操作流程、工具哈希与测试页面的提交记录(REPORT.md,openpwa.net)。
设备与主机
链接到“设备与主机”一节测试用了一台 iPhone 16 Pro(ProductType iPhone17,1),运行 iOS 18.6.2,版本号 22G100,正式版通道,Safari 18.6,浏览器语言 zh-CN,因此系统提示以中文显示。外观为浅色,06:54 到 09:31 UTC 之间的每次仪器读数都报告 prefers-color-scheme: dark 为 false。Web 检查器与远程自动化均已开启。手机没有抹掉重置,装有其他网站的主屏应用,并装有至少一个 Safari Web 扩展;功能开关、VPN 与 iCloud 专用代理的状态没有记录。主机是运行 macOS 26.3 的 Mac,用 USB 连接手机,使用 safaridriver 与 ios_webkit_debug_proxy 1.9.2(ios-webkit-debug-proxy,github.com)。
测试页面
链接到“测试页面”一节所有页面都由 openpwa.net 提供。演示应用可安装,id、start_url 与 scope 都是 /demo/,有语言切换、推送和角标页面,语言设置存在 localStorage 里。设备实验室(位于 /lab/ 下,不收录)是第二个可安装应用,有自己的 manifest 与 Service Worker,另外还有:
- 一个探测页面,没有 manifest、图标、主题色,也没有 Service Worker;
- 一个只有 manifest 的应用,带 manifest 图标、没有 apple-touch-icon;
- 标明来源的图标(红色「180 apple-touch」、蓝色「192 manifest any」);
- 几个会打印自身几何数据的状态栏变体(baseline、fixed、sticky、safe-area),以及一个单独安装、带
apple-mobile-web-app-status-bar-style: black-translucent的应用; - 一个通知记录器,其 Service Worker 用
addEventListener与self.onnotificationclick两种方式注册notificationclick,各自往 IndexedDB 写一条记录; - 一个写入 localStorage、IndexedDB 与 Cookie(
Secure、SameSite=Lax,由document.cookie设置)的存储标记; - 一个单独的、从未请求过权限的应用「Perm Test」,用
performance.now()给Notification.requestPermission()计时; - 补测用的三个应用(M1 至 M3),它们的 manifest
theme_color与页面theme-color互不相同或缺失。
主测试中每个 manifest 都声明 theme_color 为 #161616,除探测页面和一个红色变体外,每个页面都声明 #161616 的 theme-color meta。实验室的 Service Worker 在运行期间没有变化;约 08:28 UTC 的一次部署改了一个脚本,此后的读数都记录了加载的是哪个版本(实验记录,openpwa.net)。
读数采集
链接到“读数采集”一节每一步之后,智能体重启检查器代理,按 URL 与进程选中前台页面,执行一段返回 JSON 的只读表达式。这些表达式没有请求权限、订阅、注册或写入存储,记录推送端点时只取主机名。主屏应用运行在独立于 Safari 的进程中,只有前台页面能读取。WebDriver 自动化窗口只用来读取标签页一侧的值。iOS 会给每个 WebDriver 会话分配隔离的空网站数据存储。截图分析了拍摄时间与像素值,录屏切成了逐帧画面(REPORT.md,openpwa.net)。
预期与证据等级
链接到“预期与证据等级”一节测试前,我们把预期写进了为后续 iOS 27 测试准备的检查清单。中途新增步骤时,也先在实验记录里写预期,再读取页面。
结果按证据分级。A 表示仪器读数,S 表示截图或录屏,O 表示只有操作者口述。口述与记录冲突时采用记录,把冲突记为异常;更正另加条目,保留原记录。实验记录条目编号为 N01 至 N66(实验记录,openpwa.net)。
数值旁附有实验记录条目号,A 类结果的原始读数保存在数据包里(数据包,openpwa.net)。
哪些项目以应用打开
链接到“哪些项目以应用打开”一节没有 manifest 也没有图标的探测页面,从它自己的主屏图标启动后,在 Safari 的进程里以标签页的视口大小加载,navigator.standalone 为 false,匹配 display-mode: browser,读到的是 Safari 的 localStorage 值,控制页面的是 Safari 的 Service Worker(A,N23)。截图里能看到 Safari 的地址栏和工具栏(S,N63)。manifest 设置了 display: standalone 的演示应用以独立模式打开,只匹配 display-mode: standalone(A、S;N13)。这确认了 WebKit 16.4 文章中 26 之前的规则。带 manifest 页面弹出的添加面板已截图记录,标题为「添加到主屏幕」,内容包括可编辑名称、URL 和「取消」「添加」两个按钮,没有「Open as Web App」开关(S+O,N66),与 WebKit 在 iOS 26 才加入这个开关相符。
| 上下文 | navigator.standalone |
display-mode | 内部尺寸(CSS px) | 屏幕 |
|---|---|---|---|---|
| Safari 标签页(四个页面) | false | browser | 402 x 678 | 402 x 874 |
| 从图标打开的探测页面 | false | browser | 402 x 678 | 402 x 874 |
| 演示应用 | true | standalone | 402 x 812 | 402 x 874 |
| 实验室应用 | true | standalone | 402 x 812 | 402 x 874 |

同时声明了 apple-touch-icon 与 manifest 图标的实验室应用,显示的是红色的「180 apple-touch」图标。只有 manifest 的应用显示蓝色的「192 manifest any」图标,没有选用它的 512 px 图标或 maskable 图标。探测页面和一个没有图标的参考页面得到的是黑底字母图块(S,N63)。这确认了 Firtman 笔记里 apple-touch-icon 覆盖 manifest 的说法。

存储与 Cookie
链接到“存储与 Cookie”一节演示应用存于 localStorage 的语言标记,在应用首次启动时不存在,此后在两个方向上都没有传递(每一步读取一侧为 A,另一侧为操作者报告;N13、N16、N17)。实验室标记在 Safari 与两个主屏应用之间对比了三种存储(A;N18 至 N22):
| 事件(UTC) | localStorage | IndexedDB | Cookie |
|---|---|---|---|
07:13:46 Safari 写入 TAB-07:13:46 |
TAB-07:13:46 | TAB-07:13:46 | TAB-07:13:46 |
| 约 07:16 添加两个实验室应用 | |||
| 07:34:15 实验室应用首次启动 | null | null | TAB-07:13:46 |
07:37:40 实验室应用写入 APP-07:37:40 |
APP | APP | APP |
| 07:38:18 Safari 重新载入 | TAB-07:13:46 | TAB-07:13:46 | TAB-07:13:46 |
07:45:25 Safari 写入 TAB-07:45:25 |
TAB-07:45:25 | TAB-07:45:25 | TAB-07:45:25 |
| 07:45:32 只有 manifest 的应用首次启动 | null | null | TAB-07:13:46 |
localStorage 与 IndexedDB 没有复制到应用,之后两边的数据也不互通。Cookie 则复制到每个应用一次,此后两边的写入互不影响。每个应用都有自己的 Cookie 存储:只有 manifest 的应用看不到实验室应用的 APP Cookie,尽管 Cookie 路径覆盖两者。只有 manifest 的应用拿到了添加时 Safari 中的旧值,首次启动前 7 秒写入的新值没有复制过来,这与在「添加到主屏幕」时复制一致。两次操作只隔了 7 秒,仍可能是在首次启动时复制了 Safari 尚未落盘的旧值,因此复制时机的证据强度定为中等。这在 18.6.2 上确认了 WebKit 对 Safari 17.2 的描述(WebKit Features in Safari 17.2,webkit.org)。
状态栏区域
链接到“状态栏区域”一节使用默认状态栏样式(没有 meta 标签)时,每个应用内变体在 874 px 高的屏幕上内部高度都是 812 CSS px,env(safe-area-inset-top) 为 0。加上 viewport-fit=cover 后底部安全区变为 34 px,顶部仍为 0;视口依然从屏幕顶部往下 62 px 处开始,所以无论页头是 static、fixed 还是 sticky,页面内容都到不了那条条带(A;N25 至 N29)。
在演示应用、实验室应用与 Safari 标签页的全部 17 张默认样式竖屏截图中,条带在每个采样点上都是 rgb(22, 22, 22),即 #161616,从未出现 #000000。时间后面没有模糊效果,也没有内容(S,N62)。在 Safari 标签页中,蓝色页头滚走、页面顶部变白后,条带仍是 #161616,可见标签页用 theme-color meta 给状态栏区域着色,没有从页面内容取色,与 Safari 15 文章的描述一致(S)。

截图中的每个应用内页面都把 #161616 声明了两次,一次是 theme-color meta,一次是 manifest 的 theme_color,所以主测试分不出条带取的是哪一个。(在 Safari 标签页中截图的探测页面两者都没有声明,它的条带与页面自己的 #161616 页头一致。)约 10:56 UTC 的补测用了三个两种颜色互不相同的新主屏应用,加上实验室的红色变体,并在每张截图的条带内采了六个点(S,N64;操作者对四者的描述全部一致,O):
| 应用或页面 | manifest theme_color |
页面 theme-color meta |
条带 |
|---|---|---|---|
| M1 | #d00000 |
#00a050 |
#00a050 |
| M2 | 无 | #d00000 |
#d00000 |
| M3 | #00a050 |
无 | #00a050 |
| 实验室应用内的红色变体 | #161616 |
#d00000 |
#d00000 |
在 iOS 18.6.2 上,使用默认状态栏样式时,已安装应用的条带在页面有 theme-color meta 时取自它,即使与 manifest 不同也是如此;页面没有 meta 时退回 manifest 的 theme_color。红色变体说明颜色跟随当前页面变化,添加应用时没有固定这个值(N65)。manifest 规范允许浏览器让 meta 元素覆盖 manifest 颜色,但不作要求,所以这个结果在一个版本上确定了规范留给浏览器的选择(Web Application Manifest,w3.org)。它也更正了操作者早先「红色变体的条带是黑色」的报告,截图与之相反(N65-a)。未测页面不声明两种颜色的情况,也未测用 media 限定 meta、深色外观和加载后用脚本修改 meta。

在一个单独安装、使用 apple-mobile-web-app-status-bar-style: black-translucent 与 viewport-fit=cover 的应用中,视口以 402 x 874 占满屏幕,顶部安全区为 62 px,底部为 34 px(A,N55);操作者报告看到页面的蓝色页头位于白色状态栏文字后面(O)。这确认了 Apple 已归档的参考文档,以及 Firtman 笔记中 black-translucent 仍是全屏应用唯一途径的说法。没有分别安装使用 default 和 black 的应用来测试。
| 页面 | status-bar-style | viewport-fit |
内部高度 | 顶部 / 底部安全区 | 条带 |
|---|---|---|---|---|---|
| baseline、fixed、sticky | 无 | 默认 | 812 | 0 / 0 | 纯色,页面 theme-color(S) |
| safe-area | 无 | cover | 812 | 0 / 34 | 纯色,页面 theme-color(S) |
| black-translucent 应用 | black-translucent | cover | 874 | 62 / 34 | 页面画在状态栏之下(A) |
通知权限
链接到“通知权限”一节Safari 标签页中没有 Notification 与 PushManager(A)。在实验室应用中,Notification.permission 首次启动时为 default,操作者点按权限按钮后为 granted(A;N18、N32)。08:17:36 UTC 拍下的截图显示了系统提示,标题为「“PWA Lab”想给你发送通知」,按钮为「不允许」与「允许」(S,N58)。一次授权同时把 Service Worker 注册的 permissionState 与 window.pushManager.permissionState 都变为 granted(A)。
Perm Test 此前没有请求过权限,这次测试全程录屏。requestPermission() 于 09:27:59.551 UTC 调用,于 09:28:01.620 UTC 兑现,按 performance.now() 计为 2068 ms,结果为 granted;录屏中提示出现在约 70.6 s 至 72.5 s,与页面时间的偏差在 1 秒以内(A、S;N53、N54、N59)。不等待用户输入的请求会在几毫秒内兑现。这确认了 16.4 中提示必须跟在用户手势之后的规则,并给出了实测的等待时间。

推送订阅
链接到“推送订阅”一节实验室应用用 Service Worker 成功订阅,端点位于 web.push.apple.com,expirationTime 为 null,userVisibleOnly 为 true(A、S;N33)。在同一个应用中,window.pushManager.getSubscription() 返回 null,演示应用也是同样的情形(A,N41)。两个 worker 的作用域都是子路径,分别为 /lab/ 下的实验室路径与 /demo/,都不在站点根目录。WebKit 说根作用域的 worker 与 window 共享订阅;这些结果与该规则在非根作用域情形下的推论一致,根作用域的 worker 没有测试。另外,普通 Safari 标签页中存在带 subscribe、permissionState 与 getSubscription 的 window.pushManager,而那里没有 PushManager 与 Notification(A;N03、N10)。这里只读取了对象是否存在,没有在标签页中调用 subscribe()。按前期检索,这是新的细节。
notificationclick
链接到“notificationclick”一节两种上下文使用同一个 worker 脚本。我们都在 worker 启动后、脚本给 self.onnotificationclick 赋值前读取(A;N03、N18、N34):
| 表达式 | 由 Safari 标签页控制的 worker | 由主屏应用控制的 worker |
|---|---|---|
'onnotificationclick' in self |
false | true |
typeof self.onnotificationclick |
undefined | object |
'onnotificationclose' in self |
false | true |
'onpush' in self |
false | true |
'onpushsubscriptionchange' in self |
false | true |
'Notification' in self |
false | true |
'showNotification' in registration |
false | true |
'pushManager' in registration |
false | true |
typeof clients.openWindow |
function | function |
授权前后,应用一侧的值都一样。按前期检索,这项差异此前没有公开记录,它也解释了 BCD 的记录:采集器检测的属性,在 worker 由标签页控制时并不存在。随后操作者在四种情形下点按了 worker 显示的六条通知;每次点按都从两条处理路径各产生一条记录(A;N35 至 N40):
| 点按 | 情形 | 监听器记录 | 属性记录 | 导航 |
|---|---|---|---|---|
| 1 | 主屏幕上的横幅 | 08:23:07.007 | 08:23:07.008 | 聚焦已有窗口 |
| 2 | 应用在前台时的横幅 | 08:23:30.533 | 08:23:30.534 | 聚焦已有窗口 |
| 3 | 主屏幕上的横幅 | 08:24:46.071 | 08:24:46.072 | 聚焦已有窗口 |
| 4 | 通知中心 | 08:26:49.588 | 08:26:49.588 | 聚焦已有窗口 |
| 5 | 应用被划掉并重新启动之后 | 08:28:50.048 | 08:28:50.061 | 聚焦已有窗口 |
| 6 | 点按前应用已被划掉 | 08:43:09.236 | 08:43:09.245 | 聚焦已有窗口 |
两条路径在 6 次点按中都触发了,每次 clients.matchAll() 都找到一个窗口,focus() 都成功;两个处理函数都没有调用 event.preventDefault(),也没有出现 notificationclose 记录。第 6 次点按发生在划掉应用约 6 秒后,但上次重新启动时加载的页面仍然存活,点按后也成功聚焦(A,N40)。因此「没有窗口、worker 必须调用 clients.openWindow()」这条路径从未走到,测试也没有发送真实的推送消息。这确认了 #22959 中开发者的报告,并补充了两种处理函数写法的细节;对 WebKit 268797 号缺陷中「没有存活页面」的情形,这次测试没有给出任何结论。

安装 API 与角标
链接到“安装 API 与角标”一节navigator.install、BeforeInstallPromptEvent、onbeforeinstallprompt 与 getInstalledRelatedApps 在标签页和应用中都不存在(A)。演示应用已有通知权限,调用三次设置角标后,图标显示红色的「3」(S,N60);clearAppBadge() 之后角标消失,这一点只有操作者的报告(O)。这确认了 WebKit 为 16.4 宣布的 Badging API 支持(WebKit Features in Safari 16.4,webkit.org)。
观察者与工具错误
链接到“观察者与工具错误”一节记录揭示了四次观察者错误。操作者报告一个状态栏步骤跳出了应用,但页面历史长度和加载时间显示,操作者根本没有点按链接(N24、N25)。测试前没有定义「状态栏」,颜色报告说的其实是页面的蓝色页头;我们撤回了这些报告,改用像素测量条带(N46、N62)。操作者还报告首次请求没有出现权限提示,自己的截图却拍到了提示(N58)。另一次,记录者把单字回答理解成也涵盖尚未安装的应用(N50)。
工具也出过问题。WebDriver 的存储彼此隔离;检查器页面列表空了十分钟,切换 Web 检查器后才恢复;部署后 HTTP 缓存还保留着旧脚本(REPORT.md,openpwa.net)。
主屏应用的代码处理
链接到“主屏应用的代码处理”一节代码处理方式要结合测试条件看:iOS 18.6.2、iPhone 16 Pro,以及这些测试页面。
登录与存储
链接到“登录与存储”一节用户添加站点前,Safari 中已有的登录 Cookie 会复制到应用。测试用的第一方 Cookie 由脚本设置,带 Secure 和 SameSite=Lax,结果就是如此;localStorage 和 IndexedDB 中的令牌则不会复制过去。创建之后两份 Cookie 存储各自变化,所以之后在 Safari 中退出登录不会清掉应用里的副本(退出登录本身没有测试),同一个源的两次安装之间也会各自变化。登录流程可以利用安装时已存在的 Cookie,不应指望其他存储会带过去,还要处理两边逐渐不一致的情况。存储隔离条目已经按 WebKit 17.2 的来源写明了这一点。
通知点按与特性检测
链接到“通知点按与特性检测”一节在 18.6.2 上,已安装应用中的 notificationclick 处理函数无论用 addEventListener 注册还是赋给 self.onnotificationclick 都会运行,并且能聚焦已有窗口。在标签页里做特性检测看不到这一点:由标签页控制的 worker 没有 onnotificationclick、没有 Notification,也没有 showNotification。想描述这个事件的兼容性记录需要注明上下文,BCD 对 push_event 就已经这样做了。代码不应根据在已安装应用之外求值的 'onnotificationclick' in self 来决定是否注册点按处理函数。
推送订阅检查
链接到“推送订阅检查”一节Service Worker 作用域为子路径的应用,如果通过注册订阅、之后又去问 window.pushManager.getSubscription(),会得到 null,并可能误以为自己没有订阅。查询建立订阅时用的那个管理器。由于在没有 PushManager 与 Notification 的 Safari 标签页里也存在 window.pushManager,'pushManager' in window 不能用来判断「这里能用推送」。
屏幕顶部
链接到“屏幕顶部”一节使用默认样式时,在这个版本上无法把内容放到状态栏后面:布局视口从状态栏下方开始,单靠 viewport-fit=cover 只会把底边延伸出去。想让页头颜色出现在时间后面,需要 apple-mobile-web-app-status-bar-style: black-translucent 配合 viewport-fit=cover,代价是白色状态栏文字会压在页面放在那里的任何内容上。测试页没有用 env(safe-area-inset-top) 留内边距,页头照样位于时间后面;想让内容避开时间,就按 62 px 的安全区留出内边距。条带颜色本身由页面决定:在这个版本上,当前页面的 theme-color meta 优先于 manifest 的 theme_color,后者只在页面没有 meta 时生效,所以页面声明自己的颜色就能改变条带。
这些结果描述的是 22G100 版本上的一台 iPhone 16 Pro;iPadOS、其他机型与其他版本都没有测试,而这台手机之后会升级。设备没有抹掉重置,一个身份不明的 Safari Web 扩展运行在 Safari 的进程中,可能影响标签页一侧的读数。white-top、绿色背景、动态变体和深色外观下的条带颜色只有操作者口述,black-translucent 应用中时间后面的画面和清除角标也一样;这些结果标为 O,不用于结论。颜色来源补测依据截图和操作员报告,没有对这些应用做仪器读数。我们靠第二份记录发现观察者错误;缺少第二份记录的步骤可能也有同类错误,只是还没发现。读数会在页面中运行 JavaScript,并添加一个隐藏元素和一个临时属性,而且只能读取前台页面。条带颜色来自截图,截图流程没有用实测显示器校验过。只测试了一个由脚本设置的第一方 Cookie;服务端设置的、HttpOnly、会话、分区与第三方 Cookie 都没有测试。由于运行中加入了用来区分假设的步骤,实际用了约三个小时,而计划是 60 分钟;每个新增步骤的预期都在读数之前写下(实验记录,openpwa.net)。
下一次运行
链接到“下一次运行”一节这台手机升级到 iOS 27 后,我们会复查同一批页面,包括在 18.6.2 上安装的应用,以便逐项对照。颜色来源测试会增加仪器读数,还会加一个两种颜色都不声明的页面。
Cookie 复制时机会单独测:添加应用后让 Safari 写入新值,至少等两分钟再首次启动应用。测试 notificationclick 时,先用读数确认没有存活窗口,再点按通知,让 clients.openWindow() 路径运行。
站内相关条目
链接到“站内相关条目”一节- iOS 上主屏 Web 应用的存储隔离: WebKit 对已安装应用中存储与 Cookie 的记载。
- iOS Safari 上的 Web Push:主屏 Web 应用的权限、订阅与投递规则。
- iOS 添加到主屏幕:保存的站点如何成为 Web 应用或书签。
- theme_color 与 background_color: manifest 颜色成员与
theme-colormeta 元素。 - Badging API:
setAppBadge()与clearAppBadge()。 - 按版本看 iOS 上的 PWA:每个 iOS 版本的有日期记录。
待核实
链接到“待核实”一节- 既不声明
theme-colormeta、也不声明 manifesttheme_color的页面,默认状态栏条带显示什么,以及带media限定的 meta 或由脚本修改的 meta 是否生效,都没有测试。 - 在 18.6.2 上,作用域为站点根目录的 Service Worker 是否与
window.pushManager共享订阅,没有测试。 - 在暴露了
window.pushManager的 Safari 标签页中,window.pushManager.subscribe()能否工作,没有测试。 - 应用没有任何存活页面时,
notificationclick是否触发、clients.openWindow()是否成功,这条路径没有走到;测试也没有发送真实的推送消息。 - Cookie 是在「添加到主屏幕」时还是在首次启动时复制,强度定为中等:Safari 最后一次写入与第二个应用首次启动之间只隔了 7 秒。
- 服务端设置的、
HttpOnly、会话、分区与第三方 Cookie 都没有测试。 default与black状态栏样式和深色外观都没有仪器读数支持;已安装应用的横屏只有一次仪器读数记录了视口(874 x 402 中占 750 x 402),没有记录是否显示状态栏以及两侧条带的颜色。
数据可得性
链接到“数据可得性”一节数据包包括实验记录(N01 至 N66)、测试报告、测试规程、77 个原始 JSON 文件(43 个读数与 34 个元数据附属文件)、带运行时所记哈希的探测脚本、28 张截图(5 张做了遮挡)以及剪辑过的录屏与关键帧,每个文件都有 SHA-256 校验和,另有一个打包文件,以 CC BY 4.0 发布。推送端点只记录了主机名;README 列出了为发布所做的每一处改动。引用时写作「OpenPWA device test, 2026-10-20, iPhone 16 Pro, iOS 18.6.2 (22G100)」,引用单个发现时加上实验记录条目号。演示应用在 /demo/ 上线运行;实验室页面位于 /lab/ 下,不收录。
参考来源
链接到“参考来源”一节- OpenPWA device test data, iOS 18.6.2(openpwa.net)
- Test report, REPORT.md(openpwa.net)
- Headline findings, FINDINGS.md(openpwa.net)
- Lab notebook, N01 to N66(openpwa.net)
- iOS PWA Compatibility(firt.dev)
- Web Push for Web Apps on iOS and iPadOS(webkit.org)
- WebKit Features in Safari 16.4(webkit.org)
- WebKit Features in Safari 17.2(webkit.org)
- Meet Declarative Web Push(webkit.org)
- WebKit Features in Safari 18.4(webkit.org)
- WebKit Features in Safari 26.0(webkit.org)
- New WebKit Features in Safari 15(webkit.org)
- Tracking Prevention in WebKit(webkit.org)
- Bug 181849: “Add to homescreen” apps don’t share storage with Safari(bugs.webkit.org)
- Bug 268797: notificationclick events in serviceworkers not firing(bugs.webkit.org)
- mdn/browser-compat-data#22959(github.com)
- browser-compat-data: api/ServiceWorkerGlobalScope.json(github.com)
- browser-compat-data: api/Window.json(github.com)
- Supported Meta Tags(developer.apple.com)
- Configuring Web Applications(developer.apple.com)
- Web Application Manifest(w3.org)
- So what’s up with the iOS27 blur?(modernwebweekly.substack.com)
- ios-webkit-debug-proxy(github.com)