使用 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?
}
注意事项
- 权限要求 :使用
FamilyActivityPicker需要申请相应的家庭控制权限 - 图标获取限制:直接获取其他应用的图标可能受到系统限制
- 异步处理:应用信息的加载建议使用异步方式,避免阻塞 UI
- 错误处理:妥善处理可能出现的异常情况
通过以上步骤,你可以成功获取用户选择的应用的详细信息,并在界面中展示出来。
这个实现提供了完整的解决方案,包括 API 介绍、实现步骤和完整代码示例。你可以根据实际需求进行调整和优化。