What's new in Screen Time API
System & Services 进阶 20m

Screen Time API 的新功能

What's new in Screen Time API

2022年6月6日

在 Apple 官方观看视频

一句话判断

Screen Time API 不再只是家长控制工具——个人用户授权和自定义使用报告让它的应用场景大幅扩展。

这场 Session 讲了什么

iOS 15 引入的 Screen Time API 包含三个框架:Family Controls(授权入口)、Managed Settings(限制和屏蔽)、Device Activity(时间窗口和阈值响应)。但这些框架最初只支持家长对儿童设备的管控场景。

iOS 16 带来了三项重大更新。第一,Family Controls 新增个人用户授权模式——用户可以对自己的设备授权,不再限于家长管控。这意味着 Screen Time API 可以用于个人效率工具,不仅仅是家长控制 App。第二,Managed Settings Store 支持命名存储——每个进程最多创建 50 个命名 Store,且自动在 App 和 Extension 之间共享。第三,Device Activity 新增了自定义报告功能,通过 SwiftUI 构建完全自定义的使用报告 UI。

Session 用一个名为 Worklog 的示例 App 贯穿始终,展示了如何利用这些新 API 构建一个帮助职场新人养成良好习惯的工具。

值得深挖的点

  • 个人授权 vs 家长授权:个人授权模式下,用户对自己设备授权。与家长授权的关键区别是:不限制 iCloud 登出、不限制 App 删除、同一设备可以有多个 App 同时使用个人授权。这为效率类 App 打开了大门。
  • 命名 Managed Settings Store:这是最实用的新功能。你可以为不同类别创建不同的 Store(比如”游戏”Store 屏蔽游戏网站,“社交”Store 屏蔽社交媒体),系统自动应用最严格的设置。清除某个 Store 的设置不会影响其他 Store。
  • Device Activity Report:新的报告扩展点让你用 SwiftUI 构建自定义的使用报告。框架提供原始使用数据,你负责展示逻辑。报告内容通过 DeviceActivityReport.Context 关联到特定的时间窗口和过滤条件。
  • async/await 全面采用:授权请求现在完全基于 async/await,代码更简洁,错误处理更直观。

代码片段

// 个人用户授权请求
let center = AuthorizationCenter.shared
do {
    try await center.requestAuthorization(for: .individual)
    // 用户通过 Face ID/Touch ID 验证后授权成功
} catch {
    // 处理授权失败
}

// 创建命名 Managed Settings Store
let gamingStore = ManagedSettingsStore(named: "Gaming")
gamingStore.shield.webContent = .all  // 屏蔽所有游戏网站

let socialStore = ManagedSettingsStore(named: "Social")
socialStore.shield.applicationCategories = .all  // 屏蔽社交媒体

// 清除特定 Store 的设置(不影响其他 Store)
socialStore.clearAllSettings()

// 自定义 Device Activity Report
struct PieChartReport: DeviceActivityReport {
    let context: DeviceActivityReport.Context = .pieChart

    let filter: DeviceActivityFilter = {
        // 定义报告的时间范围和数据来源
        DeviceActivityFilter(
            segment: .daily(
                during: Calendar.current.dateInterval(
                    of: .day, for: Date()
                )!
            )
        )
    }()

    func makeConfiguration(
        representing data: DeviceActivityResults<ActivityCategory>
    ) -> PieChartView.Configuration {
        // 将使用数据映射到饼图配置
        var segments: [PieSegment] = []
        for await category in data {
            for await activity in category.activity {
                segments.append(
                    PieSegment(
                        name: activity.displayValue,
                        duration: activity.duration
                    )
                )
            }
        }
        return PieChartView.Configuration(segments: segments)
    }
}

最佳实践

  • 优先使用个人授权模式构建效率类工具,市场远大于家长控制
  • 为不同功能创建独立的命名 Store,利用”最严格设置优先”的特性组合管理
  • Device Activity Report 尽量在 Extension 中处理数据聚合,只把结果传给主 App
  • 授权状态变化时及时更新 UI,利用 AuthorizationCenter.$authorizationStatus 监听变化
  • 使用报告功能时注意隐私——用户数据只在他们自己的设备上处理

还有什么值得关注

  • Family Controls 的 opaque token 机制保证用户隐私,你的 App 无法知道具体屏蔽了哪些 App
  • Device Activity Extension 的运行时间和内存有限,报告逻辑要精简
  • 搭配 Focus Filters 可以构建更精细的场景化限制方案
  • App 的授权可以在”设置 > 屏幕使用时间”中被用户随时撤销
WWDC 2022