如何在iOS宿主应用中控制Safari Web扩展的启用与禁用?
iOS Safari Web扩展全局开关实现方案
由于iOS宿主应用无法直接向Web扩展后台脚本发送消息,你可以通过App Group共享存储同步开关状态,让后台脚本感知设置变化并调整Declarative Network Request规则,具体步骤如下:
1. 配置App Group权限
- 在Apple开发者后台为宿主应用和Web扩展注册同一个App Group(格式为
group.com.yourdomain.yourapp) - 在Xcode中,分别给宿主和扩展的
Signing & Capabilities添加App Groups能力,并勾选对应的Group ID
2. 宿主应用同步开关状态
在开关的交互事件中,将状态写入共享的UserDefaults:
@IBAction func toggleExtensionStatus(_ sender: UISwitch) { guard let sharedDefaults = UserDefaults(suiteName: "group.com.yourdomain.yourapp") else { return } sharedDefaults.set(sender.isOn, forKey: "ExtensionGlobalEnabled") sharedDefaults.synchronize() }
3. Web扩展后台脚本处理状态变化
方案1:监听设置变化(推荐)
Safari Web扩展的后台脚本可以直接监听共享设置的变化,无需轮询:
// 后台脚本 // 同步状态逻辑 function syncExtensionStatus(isEnabled) { if (isEnabled) { // 启用内容过滤规则 chrome.declarativeNetRequest.updateDynamicRules({ addRules: YOUR_ACTIVE_RULES, removeRuleIds: YOUR_INACTIVE_RULE_IDS }); } else { // 移除所有过滤规则 chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: ALL_RULE_IDS }); } } // 首次加载时同步初始状态 const initialEnabled = safari.extension.settings.getItem("ExtensionGlobalEnabled") === "true"; syncExtensionStatus(initialEnabled); // 监听设置变更 safari.extension.settings.addEventListener("change", (event) => { if (event.key === "ExtensionGlobalEnabled") { syncExtensionStatus(event.newValue === "true"); } });
方案2:定时轮询(兼容旧版本)
如果监听方式存在兼容性问题,可采用定时轮询检查状态:
// 后台脚本 function checkAndSyncStatus() { const isEnabled = safari.extension.settings.getItem("ExtensionGlobalEnabled") === "true"; syncExtensionStatus(isEnabled); } // 初始同步 checkAndSyncStatus(); // 每30秒检查一次状态 setInterval(checkAndSyncStatus, 30000);
关键注意点
- 规则ID管理:确保启用/禁用操作能精准匹配对应规则ID,避免出现规则冲突或漏操作
- 规则分层优化:可将基础规则放在静态规则文件中,通过动态规则的启用/禁用控制整体开关,提升运行效率
- 默认状态设置:首次安装时需在宿主或扩展中配置默认开关状态(比如默认开启)
内容的提问来源于stack exchange,提问作者4ntoine
相关产品推荐
相关产品推荐

