# 面向 iOS 发布 PWA

> 一份有来源依据的 iOS PWA 检查清单，覆盖 manifest、Safari 主屏幕流程、显示模式检测和通知权限。

Safari 允许用户把 PWA 添加到 iOS 主屏幕。准备好 manifest 和添加步骤，检测显示模式，并在用户操作后请求通知权限。获得权限还不等于完成推送订阅。

## 平台支持

iOS 26 上的 Safari 26 默认将添加到主屏幕的网站作为 Web 应用打开，用户也可关闭
**Open as Web App** 来创建书签。WebKit 记录了 iOS 与 iPadOS 16.4 主屏幕 Web 应用的
Web Push。它的第三方浏览器添加路径要求具备 Apple 的托管 Web 浏览器 entitlement。

## 提供 manifest

Web 应用 manifest 提供应用名称和图标等安装元数据。`display` 成员表达首选显示模式，
`start_url` 是浏览器可以忽略的提示。当 manifest 提供图标时，Safari 26 会使用这些图标。

```json
{
  "name": "现场笔记",
  "short_name": "笔记",
  "start_url": "/",
  "display": "standalone",
  "icons": [
    { "src": "/icons/notes-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/notes-512.png", "sizes": "512x512", "type": "image/png" }
  ]
}
```

在文档 head 中使用 `<link rel="manifest" href="/manifest.webmanifest">` 链接 manifest。

## 说明 Safari 添加流程

Apple 的 iPhone 指南要求用户打开 Safari 的分享菜单，选择 **Add to Home Screen**，
开启 **Open as Web App**，再选择 **Add**。当文档不处于独立显示模式时，显示这些操作
说明。

## 通过用户操作请求通知权限

WebKit 说明，iOS 或 iPadOS 16.4 上的主屏幕 Web 应用必须响应直接的用户交互来请求 Web
Push 权限。MDN 同样把 `Notification.requestPermission()` 放在点击处理器中。权限只是其中一步；
WebKit 将标准 Web Push 描述为 Push API、Notifications API 和 Service Worker 共同工作。

## 示例

这些完整页面分别覆盖显示模式分支和权限分支。当所检测的能力或状态不存在时，两者都会
保留可见的回退路径。

### 在非独立模式中显示 Safari 操作说明

用 `display-mode` 媒体特性判断是否处于独立模式，并在该模式中隐藏说明。在其他显示模式中，有文档
依据的 Safari 路径会保持可见。

```html
<!doctype html>
<html lang="zh-CN">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>安装现场笔记</title>
  <p id="install-hint">在 Safari 中打开分享，再选择 Add to Home Screen。</p>
  <script>
    const installHint = document.querySelector('#install-hint');
    const standalone = window.matchMedia('(display-mode: standalone)').matches;

    if (standalone) {
      installHint.hidden = true;
    } else {
      installHint.hidden = false;
    }
  </script>
</html>
```

MDN 提醒，显示模式并不直接证明安装状态，因此这个示例只用它判断当前视图中是否需要
显示操作说明。

### 准确报告通知权限

只报告权限请求的结果。如果 Notifications API 不存在或结果不是 `granted`，页面会保留
应用内更新路径。

```html
<!doctype html>
<html lang="zh-CN">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>现场笔记通知权限</title>
  <button id="permission" type="button">请求通知权限</button>
  <p id="status" aria-live="polite">可在应用内查看更新。</p>
  <script>
    const status = document.querySelector('#status');

    document.querySelector('#permission').addEventListener('click', async () => {
      if (!('Notification' in window)) {
        status.textContent = '仍可在应用内查看更新。';
        return;
      }

      const permission = await Notification.requestPermission();
      if (permission === 'granted') {
        status.textContent = '已获得通知权限。';
      } else {
        status.textContent = '仍可在应用内查看更新。';
      }
    });
  </script>
</html>
```

成功文本没有宣称推送已经启用，因为这个示例没有创建 Push API 订阅。

:::caution
WebKit 要求 iOS 与 iPadOS 16.4 上的 Web Push 权限请求紧随直接的用户交互。不要在页面
加载期间调用它。
:::

## 另请参阅

- [Turn a website into an app in Safari on iPhone（Apple 支持）](https://support.apple.com/guide/iphone/open-as-web-app-iphea86e5236/ios)
- [Web Push for Web Apps on iOS and iPadOS（WebKit）](https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/)
- [让它可安装](/zh/guides/installable/)
- [iOS 与 Safari 上的 PWA](/zh/reference/platforms/ios-safari/)
- [iOS 添加到主屏幕](/zh/reference/installation/ios-add-to-home-screen/)