You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ShieldActionExtension中使用completionHandler(.defer)实现应用访问授权通知?

实现Screen Time屏蔽界面的访问许可信号发送

从WWDC关于Screen Time API的视频中了解到:
“屏蔽响应可以是关闭被屏蔽应用,或是延迟操作并重绘屏蔽配置。”
“屏蔽的延迟操作功能非常强大,因为它能让屏蔽界面在等待后续操作信号的同时更新外观。例如,当孩子点击‘请求访问’时,可用于显示屏蔽界面正在等待监护人操作。”

我的需求是:引导用户从屏蔽配置界面跳转至我的应用,通过按钮向等待状态的屏蔽界面发送访问许可信号,允许用户访问目标应用。

实现方案

由于屏蔽动作扩展(Shield Action Extension)与主应用属于不同进程,需通过App Group实现跨进程通信,步骤如下:

  • 配置App Group
    在Xcode中为主应用和屏蔽动作扩展添加相同的App Group标识符(如group.com.yourdomain.yourapp),并确保两者的Info.plist均包含该配置。

  • 修改屏蔽动作扩展代码
    触发延迟响应后,监听主应用发送的许可信号并完成授权:

import ManagedSettings
import Combine

class MyShieldActionExtension: ShieldActionHandler {
    private var cancellables = Set<AnyCancellable>()
    // 共享UserDefaults用于跨进程通信
    private let sharedDefaults = UserDefaults(suiteName: "group.com.yourdomain.yourapp")!

    override func handle(
        action: ShieldAction,
        for application: Application,
        completionHandler: @escaping (ShieldActionResponse) -> Void
    ) {
        switch action {
        case .primaryButtonPressed:
            // 发送延迟响应,让屏蔽界面保持等待状态
            completionHandler(.defer)
            
            // 监听主应用的许可信号
            sharedDefaults.publisher(for: \.allowAccess)
                .filter { $0 }
                .first()
                .sink { [weak self] _ in
                    // 收到许可后关闭屏蔽界面,允许访问目标应用
                    completionHandler(.close)
                    // 重置信号状态
                    self?.sharedDefaults.set(false, forKey: "allowAccess")
                }
                .store(in: &cancellables)
            
            // 跳转至主应用(需提前配置URL Scheme)
            if let url = URL(string: "yourapp://grant-access?bundleID=\(application.bundleID)") {
                open(url)
            }
            
        case .secondaryButtonPressed:
            completionHandler(.close)
            
        @unknown default:
            fatalError()
        }
    }
}
  • 主应用中实现许可按钮逻辑
    在按钮点击事件中通过共享UserDefaults发送许可信号:
import UIKit

class GrantAccessViewController: UIViewController {
    private let sharedDefaults = UserDefaults(suiteName: "group.com.yourdomain.yourapp")!
    var targetBundleID: String?

    @IBAction func allowAccessTapped(_ sender: UIButton) {
        // 设置许可信号
        sharedDefaults.set(true, forKey: "allowAccess")
        // 关闭页面返回屏蔽界面
        dismiss(animated: true)
    }
}
  • 配置URL Scheme
    在主应用的Info.plist中添加自定义URL Scheme(如yourapp),并在SceneDelegate或AppDelegate中处理URL跳转,解析目标应用的Bundle ID并展示授权页面。

内容的提问来源于stack exchange,提问作者David Johansen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:35:15