iOS家长控制应用:父设备无法获取子设备应用使用时长
问题诊断与解决方案
1. 父设备授权类型错误(核心问题)
你在父设备使用的.individual授权仅能访问当前设备的个人Screen Time数据,无法获取家庭中子设备的使用数据。必须切换为.familyManager授权——这是家庭组织者身份获取子设备数据的必要权限。
修改父设备的授权代码:
// 替换原有的.individual,改为.familyManager do { let status = try await AuthorizationCenter.shared.requestAuthorization(for: .familyManager) // 确认授权状态为.authorized print("授权状态:\(status)") } catch { print("授权失败:\(error.localizedDescription)") }
注意:必须由家庭组织者的Apple ID在父设备上执行此授权,且需在系统设置中确认授予应用家庭管理权限。
2. 验证子设备的授权状态
子设备的.child授权需确保完全生效,不能仅用try?忽略错误,应明确检查授权状态:
do { let status = try await AuthorizationCenter.shared.requestAuthorization(for: .child) guard status == .authorized else { print("子设备授权未通过") return } } catch { print("子设备授权失败:\(error.localizedDescription)") }
同时确认子设备的Apple ID已添加到父设备的家庭共享中,且Screen Time的内容与隐私访问限制中允许你的应用访问Screen Time数据。
3. 修正DeviceActivityFilter的时间范围
你当前的筛选器使用.daily(during: 周区间)存在逻辑矛盾:.daily需要的是单日区间,而非整周范围。若仅需获取当天的使用数据,应修改为:
self.filter = DeviceActivityFilter( segment: .daily( during: Calendar.current.dateInterval(of: .day, for: .now)! ), users: .children, devices: .init([.iPhone, .iPad]), applications: selectedApps, categories: selectedCategories, webDomains: selectedWebDomains )
错误的时间区间会导致系统返回空数据,因为当前时间无法匹配你指定的周区间规则。
4. 确保家庭活动选择的同步
父设备通过familyActivityPicker选择的应用,需确保对应的ActivitySelection数据同步到家庭共享中:
- 父设备和子设备均需开启iCloud家庭共享(设置→[你的名字]→家庭共享→Screen Time)
- 在Xcode项目配置的
Signing & Capabilities中为应用添加iCloud能力(选择CloudKit或至少启用iCloud Documents),Screen Time的活动选择数据依赖iCloud同步。
5. 检查Info.plist权限描述
父设备和子设备的应用都需在Info.plist中添加NSFamilyActivityUsageDescription,说明应用访问Screen Time数据的原因:
<key>NSFamilyActivityUsageDescription</key> <string>需要访问Screen Time数据以监控孩子的应用使用情况</string>
缺少该描述会导致系统拒绝应用的授权请求。
6. 排查数据获取逻辑
在TotalActivityReport的makeConfiguration方法中添加日志,确认数据是否存在或解析逻辑是否有问题:
func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> String { var result: [String] = [] print("数据项总数:\(data.count)") for await item in data { print("设备名称:\(item.device.localizedName)") for await segment in item.activitySegments { print("时间区间:\(segment.dateInterval)") for await category in segment.categories { print("活动分类:\(category.category.localizedName)") for await application in category.applications { let name = application.application.localizedDisplayName ?? "unknown" let time = application.totalActivityDuration print("应用:\(name),时长:\(time)") result.append("\(name): \(time)") } } } } return result.joined(separator: ", ") }
内容的提问来源于stack exchange,提问作者Andrey Chernyshev
相关产品推荐
相关产品推荐

