Apple 的 ActivityKit 是在 iOS 16 引入的一项框架,主要用于支持 Live Activities(实时活动) 的功能。它允许 App 在锁屏和动态岛(iPhone 14 Pro 及以上)中显示动态更新的实时信息,比如计程车到达时间、外卖配送状态、比赛比分等。
下面将系统性、详细地介绍 ActivityKit 的使用方式,包括其工作机制、关键组件、使用流程、注意事项和最佳实践。
🧠 一、ActivityKit 工作机制概览 #
Live Activities 是一种临时的信息展示,允许应用在 锁屏界面 和(支持的设备上)动态岛中展示活动状态,并通过推送或本地更新实时刷新内容。
由 App 启动并控制展示
可以通过 本地更新 或 远程推送更新
活动是临时的,最多持续 8 小时(可延长到 12 小时)
用户可通过交互或系统事件(如结束导航)关闭活动
🧱 二、核心组成部分 #
ActivityKit 的使用主要依赖以下几个核心组成部分:
1. ActivityAttributes
#
定义实时活动的静态和动态属性。
struct DeliveryAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var estimatedDeliveryTime: Date
var driverLocation: CLLocation
}
var orderID: String // 静态属性
}
ContentState
:表示会变化的内容,需实现Codable
和Hashable
外层结构定义静态不变属性
2. Activity<Attributes>
#
ActivityKit 提供的主要 API 接口,用于启动、更新、终止 Live Activity。
🧭 三、基本使用流程 #
步骤一:引入框架 #
import ActivityKit
步骤二:定义 ActivityAttributes
#
struct TimerAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var remainingTime: TimeInterval
}
var taskName: String
}
步骤三:启动一个 Activity #
let attributes = TimerAttributes(taskName: "Focus Timer")
let initialState = TimerAttributes.ContentState(remainingTime: 1500)
do {
let activity = try Activity<TimerAttributes>.request(
attributes: attributes,
contentState: initialState,
pushType: nil // 可为 .token 获取远程推送权限
)
print("Activity started with ID: \(activity.id)")
} catch {
print("Failed to start activity: \(error)")
}
步骤四:更新 Activity #
Task {
await activity.update(using: TimerAttributes.ContentState(remainingTime: 1400))
}
步骤五:结束 Activity #
Task {
await activity.end(dismissalPolicy: .immediate)
}
📱 四、在 Widget Extension 中显示 Live Activity #
Live Activities 的 UI 是通过 Widget Extension 的新区域展示:
1. 创建 Widget Extension 并实现 ActivityConfiguration
#
struct TimerLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: TimerAttributes.self) { context in
// Lock screen / Dynamic Island expanded UI
VStack {
Text(context.attributes.taskName)
Text("剩余时间: \(Int(context.state.remainingTime)) 秒")
}
.padding()
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
Text("⏳")
}
DynamicIslandExpandedRegion(.trailing) {
Text("\(Int(context.state.remainingTime))s")
}
} compactLeading: {
Text("⏳")
} compactTrailing: {
Text("\(Int(context.state.remainingTime))s")
} minimal: {
Text("⏳")
}
}
}
}
2. 配置 Extension #
在 Info.plist
中确保包含:
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>com.apple.widgetkit.live-activity</key>
<true/>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
📡 五、远程推送更新(可选) #
如果你想通过服务器远程更新 Live Activity,需要:
1. 开启 Push Type
#
let activity = try Activity<TimerAttributes>.request(
attributes: attributes,
contentState: initialState,
pushType: .token
)
2. 获取推送令牌(token) #
if let token = activity.pushToken {
let tokenString = token.map { String(format: "%02x", $0) }.joined()
// 发送给服务器用于后续推送
}
3. 服务器推送格式(HTTP POST) #
{
"aps": {
"timestamp": 1680000000,
"event": "update",
"content-state": {
"remainingTime": 900
}
}
}
并发送至 Apple Live Activities 推送服务器的对应 URL。
🚧 六、注意事项和最佳实践 #
设备支持限制:
Live Activities 显示在锁屏:iPhone 支持 iOS 16.1+
动态岛:仅支持 iPhone 14 Pro 及以上
生命周期管理:
系统可能因内存、时间等原因中断 Live Activity
最多可运行 8 小时(后台延长到 12 小时)
数据同步策略:
使用后台任务或本地定时器定期更新状态
网络活动应谨慎管理,避免频繁请求
UI 简洁性:
尽量简洁明了,不要塞入复杂交互或大量文本
避免动画滥用,关注用户信息获取效率
🧪 七、测试与调试 #
在 模拟器 中无法测试动态岛功能,需使用真机
可以通过 Xcode 的 Live Activity Debugger 查看当前 Activity
使用
activity.id
追踪调试状态