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 介绍、实现步骤和完整代码示例。你可以根据实际需求进行调整和优化。

相关推荐
徐同保12 小时前
通过ip访问nginx的服务时,被第一个server重定向了,通过设置default_server解决这个问题
ios·iphone
2501_9159184116 小时前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
2501_9160074718 小时前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
夏幻灵1 天前
HTTPS全面解析:原理、加密机制与证书体
ios·iphone
TheNextByte11 天前
如何在iPhone上恢复已删除的笔记的综合指南
笔记·ios·iphone
rose and war1 天前
python和jinja版本问题导致的访问报500
python·ios
fendoudexiaoniao_ios1 天前
iOS 列表拖拽cell排序
ios·swift
2501_915106322 天前
当 Perfdog 开始收费之后,我重新整理了一替代方案
android·ios·小程序·https·uni-app·iphone·webview
2501_915918412 天前
中小团队发布,跨平台 iOS 上架,证书、描述文件创建管理,测试分发一体化方案
android·ios·小程序·https·uni-app·iphone·webview
家里有只小肥猫2 天前
uniApp打包ios报错
ios·uni-app