screen time api - FamilyActivityPicker 获取选中应用

使用 FamilyActivityPicker 获取选中应用的详细信息

在 iOS 15+ 中,FamilyActivityPicker 是家庭控制功能的重要组成部分,允许用户选择要监控或限制的应用。但选择后如何获取应用的详细信息(如图标、名称等)呢?本文将详细介绍相关 API 和使用方法。

相关 API 介绍

1. FamilyActivitySelection

  • 作用:表示用户选择的应用程序、网站或类别的集合
  • 包含属性
    • applications:选中的应用程序集合
    • categories:选中的应用类别集合
    • webDomains:选中的网站域名集合

2. Application

  • 作用:代表一个具体的应用程序
  • 关键属性
    • token:应用的唯一标识符
    • localizedDisplayName:本地化的应用名称
    • bundleIdentifier:应用的 Bundle ID

3. AppMetadata

  • 作用:提供应用程序的元数据信息
  • 获取方式 :通过 AppMetadata(token:) 初始化器

实现步骤

步骤 1:创建状态管理

swift 复制代码
import SwiftUI
import FamilyControls

struct ContentView: View {
    @State private var selection = FamilyActivitySelection()
    @State private var selectedApps: [AppInfo] = []
    
    var body: some View {
        VStack {
            // 选择器
            FamilyActivityPicker(selection: $selection)
            
            // 显示选中应用信息
            List(selectedApps, id: \.bundleIdentifier) { app in
                HStack {
                    if let image = app.icon {
                        Image(uiImage: image)
                            .resizable()
                            .frame(width: 40, height: 40)
                            .cornerable(8)
                    }
                    VStack(alignment: .leading) {
                        Text(app.name)
                            .font(.headline)
                        Text(app.bundleIdentifier)
                            .font(.caption)
                            .foregroundColor(.gray)
                    }
                }
            }
        }
        .onChange(of: selection) { newValue in
            loadSelectedAppsInfo()
        }
    }
}

步骤 2:定义应用信息模型

swift 复制代码
struct AppInfo {
    let token: ApplicationToken
    let name: String
    let bundleIdentifier: String
    let icon: UIImage?
}

步骤 3:加载应用详细信息

swift 复制代码
extension ContentView {
    private func loadSelectedAppsInfo() {
        selectedApps.removeAll()
        
        // 遍历选中的所有应用
        for application in selection.applications {
            let appInfo = createAppInfo(from: application)
            selectedApps.append(appInfo)
        }
    }
    
    private func createAppInfo(from application: Application) -> AppInfo {
        // 获取应用显示名称
        let displayName = application.localizedDisplayName ?? "未知应用"
        
        // 获取 Bundle Identifier
        let bundleID = application.bundleIdentifier ?? "未知 Bundle ID"
        
        // 获取应用图标
        let appIcon = loadAppIcon(for: application.token)
        
        return AppInfo(
            token: application.token,
            name: displayName,
            bundleIdentifier: bundleID,
            icon: appIcon
        )
    }
}

步骤 4:加载应用图标

swift 复制代码
extension ContentView {
    private func loadAppIcon(for token: ApplicationToken) -> UIImage? {
        do {
            // 通过 AppMetadata 获取应用信息
            let metadata = try AppMetadata(token: token)
            
            // 获取应用图标(需要处理权限和异步加载)
            // 注意:实际图标的获取可能需要额外的权限或使用其他方法
            return nil // 这里需要根据具体实现调整
            
        } catch {
            print("获取应用元数据失败: \(error)")
            return nil
        }
    }
}

完整示例代码

swift 复制代码
import SwiftUI
import FamilyControls

struct FamilyActivityAppView: View {
    @State private var selection = FamilyActivitySelection()
    @State private var selectedApps: [AppInfo] = []
    
    var body: some View {
        NavigationView {
            VStack(spacing: 20) {
                Text("选择要管理的应用")
                    .font(.title2)
                    .padding()
                
                FamilyActivityPicker(selection: $selection)
                    .frame(height: 300)
                
                Divider()
                
                Text("已选择的应用 (\(selectedApps.count))")
                    .font(.headline)
                
                List(selectedApps, id: \.bundleIdentifier) { app in
                    AppInfoRow(appInfo: app)
                }
                .listStyle(PlainListStyle())
            }
            .padding()
            .navigationTitle("应用管理")
        }
        .onChange(of: selection) { newValue in
            updateSelectedApps()
        }
    }
    
    private func updateSelectedApps() {
        Task {
            var apps: [AppInfo] = []
            
            for application in selection.applications {
                let appInfo = await createAppInfo(from: application)
                apps.append(appInfo)
            }
            
            await MainActor.run {
                selectedApps = apps
            }
        }
    }
    
    private func createAppInfo(from application: Application) async -> AppInfo {
        let displayName = application.localizedDisplayName ?? "未知应用"
        let bundleID = application.bundleIdentifier ?? "未知"
        
        // 异步加载应用图标
        let icon = await loadAppIcon(for: application.token)
        
        return AppInfo(
            token: application.token,
            name: displayName,
            bundleIdentifier: bundleID,
            icon: icon
        )
    }
    
    private func loadAppIcon(for token: ApplicationToken) async -> UIImage? {
        // 这里可以实现具体的图标加载逻辑
        // 可能需要使用其他系统 API 或第三方库
        return nil
    }
}

struct AppInfoRow: View {
    let appInfo: AppInfo
    
    var body: some View {
        HStack(spacing: 12) {
            if let image = appInfo.icon {
                Image(uiImage: image)
                    .resizable()
                    .frame(width: 40, height: 40)
                    .cornerRadius(8)
            } else {
                Rectangle()
                    .fill(Color.gray.opacity(0.3))
                    .frame(width: 40, height: 40)
                    .cornerRadius(8)
                    .overlay(
                        Image(systemName: "app")
                            .foregroundColor(.gray)
                    )
            }
            
            VStack(alignment: .leading, spacing: 4) {
                Text(appInfo.name)
                    .font(.headline)
                Text(appInfo.bundleIdentifier)
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
            
            Spacer()
        }
        .padding(.vertical, 4)
    }
}

struct AppInfo {
    let token: ApplicationToken
    let name: String
    let bundleIdentifier: String
    let icon: UIImage?
}

注意事项

  1. 权限要求 :使用 FamilyActivityPicker 需要申请相应的家庭控制权限
  2. 图标获取限制:直接获取其他应用的图标可能受到系统限制
  3. 异步处理:应用信息的加载建议使用异步方式,避免阻塞 UI
  4. 错误处理:妥善处理可能出现的异常情况

通过以上步骤,你可以成功获取用户选择的应用的详细信息,并在界面中展示出来。

这个实现提供了完整的解决方案,包括 API 介绍、实现步骤和完整代码示例。你可以根据实际需求进行调整和优化。

相关推荐
2501_915106322 小时前
iOS 抓包工具在不同场景的实际作用
android·macos·ios·小程序·uni-app·cocoa·iphone
FourV大大2 小时前
iOS原生和UniApp通信
ios·uni-app·cocoa
Edward.W2 小时前
Android (ADB)、iOS、OpenHarmony 常用调试命令对照表
android·ios·adb
sweet丶3 小时前
CocoaPods Podfile优化设置手册-持续更新
ios·架构
karshey18 小时前
【IOS webview】h5页面播放视频时,IOS系统显示设置的icon
前端·ios
游戏开发爱好者818 小时前
抓包工具有哪些?代理抓包、数据流抓包、拦截转发工具
android·ios·小程序·https·uni-app·iphone·webview
bybitq20 小时前
Go函数闭包实战-复用函数
ios·golang·xcode
renke336421 小时前
Flutter 2025 跨平台工程体系:从 iOS/Android 到 Web/Desktop,构建真正“一次编写,全端运行”的产品
android·flutter·ios