发布 Safari 扩展到 iOS 应用商店
本文最后更新于:2025年8月13日 下午
背景
今年以来,吾辈开始发布一些 Safari 扩展程序到 AppStore 中,由于吾辈并不使用 iPhone,所以仅发布了 Mac 版本。而这个月吾辈开始实践全平台浏览器扩展的开发,即为所有主流的桌面浏览器(Chrome/Safari/Edge/Firefox)和所有支持扩展的移动端浏览器(Kiwi/Edge/Safari/Firefox)发布相同的插件,这让吾辈将发布 iOS Safari 扩展重新提上日程。
关于如何转换 Chrome 扩展为 Safari 扩展,请参考 转换 Chrome Extension 为 Safari 版本
过程
在已经有一个 Mac Safari 扩展的情况下,为它发布到 iOS 版本理论上很简单。但发布之前,必须通过模拟器调试确保没有漏洞。
使用模拟器测试
首先,在 Target 中选择 iOS 平台,然后选择一个模拟器,建议 iPhone 16 Pro,最后点击 Build 按钮。
其次,模拟器中的 iOS 扩展的封装 App 就会自动打开。
再其次,点击模拟器顶部工具栏的 Home 图标,返回桌面,打开 Settings > Apps > Safari > Extensions 中,即可看到刚刚 Build 的扩展。默认情况下它应该是 Disable 的,进入然后 Enable 即可。如果你无法找到刚刚 Build 的扩展,请参考下面的问题,就我而言,在排查问题的过程中 Claude 4.1 Opus 确实给了不错的提示,让吾辈意识到排查错误的方向和关键词是什么。
最后,点击 Home 回到桌面,找到 Safari 打开,你应该能在浏览器工具栏看到刚刚 Build 的扩展。
参考: Apple 官方视频 2022
发布到 AppStore
在测试完成确认没有漏洞之后,就可以发布到 AppStore 了。
首先,在 Xcode 中选择 Product > Archive 进行打包。
其次,在弹窗中点击 Distribute App 按钮,接着选择 App Store Connect 作为分发渠道,最后点击 Distribute 按钮,你的 App 就会开始上传到 AppStore 了。
但请注意,上传完成之后并未发布,只是上传了一个构建包,还需要到 App Store Connect 添加版本信息、App 描述、截图等一系列常规信息,并提交审核才能最终发布。
问题
如果没有报错但同时也不生效,那可能不是你的错,只能怪 Apple/Safari 的开发体验太糟。
iOS 里面的 Settings > Apps 中看不到任何 App
如图
根据这个 社区 issue,可以知道是 18.2 的 bug,升级到 18.4 解决。
验证
在 Settings > Safari > Extensions 中始终看不到开发的扩展
如图
升级至最新版的 XCode 及虚拟机解决,就吾辈而言,是 XCode 16.4 及 iOS 18.4 的虚拟机。
验证方法是通过 XCode 创建一个全新的 Safari Extension 项目,然后 Build 并检查 Settings > Safari > Extensions 中是否能看到。
Apple 的官方文档几乎没什么用 https://developer.apple.com/documentation/safariservices/troubleshooting-your-safari-web-extension
但吾辈看到一个今年刚出的视频感觉很有帮助 https://www.youtube.com/watch?v=DZe7L70CDPc
在 Background Script 中发起的网络请求不会自动带上 cookie
例如下面这段代码在 Chrome/Firefox 中都是正常的,但在 Safari 中就无法工作。
1 |
|
似乎和下面几个 Issue 有关,Tampermonkey 扩展也踩过坑,需要调研一下它是如何实现的。
- https://github.com/Tampermonkey/tampermonkey/issues/786
- https://github.com/Tampermonkey/tampermonkey/issues/1258#issuecomment-2485870092
Tampermonkey 似乎也找到了绕过 notifications api 缺失的问题,参考 https://github.com/Tampermonkey/tampermonkey/issues/1258#issuecomment-2488015079
CJK 输入法输入的空格不是 \u0020,而是 \u3000
一个很小的问题,CJK 输入法在 Mac 上输入的字符是 \u0020
,即便输入的是中文的空格,但 keydown
事件中仍然识别为标准的 \u0020
。
例如
1 |
|
而在 iOS Safari 上,输入中文空格后,在 beforeinput
事件中,e.data 是 \u3000
。
1 |
|
所以针对 iOS Safari 必须小心处理输入相关的事件。
如果发布区域包含国区并存在 LLM 相关功能,则需要额外注意
例如,在插件中使用了 OpenAI 的 API 实现部分功能,发布到国区就无法过审。Apple 声称根据 MIIT(工信部)的要求,所有 AI 相关的 App 都必须报备取得资质。如果是个人开发者,建议直接放弃国区。Fuck of MIIT。
总结
截止目前为止,吾辈已经成功发布了两个全平台浏览器扩展,分别是
- Redirector: https://rxliuli.com/project/redirector/
- IDBPort: https://rxliuli.com/project/idbport/
发布 Safari 扩展虽然有趣,却也让人意识到 Safari 扩展的开发体验有多么糟糕,吾辈在开发过程中踩了不少坑,也浪费了不少时间。