iOS 实时活动(Live Activity)开发指南
1. 引言实时活动Live Activity是 iOS 16.1 引入的一项功能它允许应用在锁屏界面和灵动岛Dynamic Island上持续展示实时更新的信息例如外卖配送进度、体育比赛比分、航班动态等。用户无需解锁手机或打开应用就能一眼获取关键信息。本文将从零开始系统讲解 Live Activity 的开发流程包括项目配置、ActivityKit 框架的使用、UI 构建、动态数据更新以及注意事项帮助你快速上手并落地到实际业务中。2. 核心概念在动手编码之前先理解 Live Activity 的几个核心概念这有助于你把握整体架构。ActivityKitiOS 16.1 引入的官方框架负责 Live Activity 的创建、更新和结束。ActivityAttributes描述 Live Activity 静态内容的协议例如一场球赛的对阵双方、开赛时间等。ContentState描述 Live Activity 动态内容的协议例如当前比分、比赛进行到第几分钟等。灵动岛Dynamic IslandiPhone 14 Pro 及以上机型的交互区域Live Activity 可以在此紧凑展示。锁屏界面Live Activity 在锁屏上以较大尺寸展示可包含更多信息。3. 项目配置要使用 Live Activity首先需要在 Xcode 中完成以下配置步骤。3.1 开启 Capability在 Xcode 中选中你的 Target进入Signing Capabilities点击 Capability搜索并添加Live Activities。这是使用 ActivityKit 的前提条件。3.2 Info.plist 配置在 Info.plist 中添加以下键值用于声明应用支持实时活动keyNSSupportsLiveActivities/key true/如果你的应用需要支持用户手动结束实时活动还需要添加keyNSSupportsLiveActivitiesFrequentUpdates/key true/3.3 部署目标Live Activity 要求 iOS 16.1 及以上版本请在 Target 的Deployment Info中将最低部署版本设置为 16.1 或更高。4. 定义 ActivityAttributes 和 ContentState接下来我们定义一个配送场景的 Live Activity。首先创建ActivityAttributes和ContentState。import ActivityKit struct DeliveryActivityAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { // 动态内容当前配送状态描述 var status: String // 动态内容预计剩余分钟数 var estimatedArrivalMinutes: Int } // 静态内容订单号 var orderNumber: String // 静态内容配送地址 var deliveryAddress: String }这里将订单号和配送地址作为静态属性在活动创建时确定配送状态和预计剩余时间作为动态状态可以在活动进行中多次更新。5. 创建 Live Activity使用Activity.request方法创建实时活动。以下代码展示了如何发起一个配送活动的请求。import ActivityKit func startDeliveryActivity(orderNumber: String, address: String) { let attributes DeliveryActivityAttributes( orderNumber: orderNumber, deliveryAddress: address ) let initialState DeliveryActivityAttributes.ContentState( status: 商家已接单, estimatedArrivalMinutes: 45 ) let content ActivityContent( state: initialState, staleDate: Date().addingTimeInterval(60 * 60) ) do { let activity try Activity.request( attributes: attributes, content: content ) print(Live Activity 已创建: \(activity.id)) } catch { print(创建失败: \(error.localizedDescription)) } }创建成功后系统会返回一个Activity实例你可以通过它的id在后续更新或结束该活动时进行定位。6. 构建 Live Activity UILive Activity 的界面使用 SwiftUI 构建并通过ActivityConfiguration进行注册。你需要为灵动岛和锁屏分别设计视图。6.1 注册 ActivityConfiguration在 SwiftUI 的App入口或主视图中使用ActivityConfiguration注册你的活动类型。import SwiftUI import ActivityKit main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } .activityConfiguration(for: DeliveryActivityAttributes.self) { context in // 灵动岛视图 DeliveryLiveActivityView(context: context) } lockScreen: { context in // 锁屏视图 DeliveryLockScreenView(context: context) } } }6.2 灵动岛视图灵动岛空间有限视图应保持简洁通常只展示核心信息。struct DeliveryLiveActivityView: View { let context: ActivityViewContextDeliveryActivityAttributes var body: some View { HStack { Image(systemName: shippingbox.fill) .foregroundColor(.white) VStack(alignment: .leading) { Text(context.state.status) .font(.headline) .foregroundColor(.white) Text(预计 \(context.state.estimatedArrivalMinutes) 分钟) .font(.caption) .foregroundColor(.white.opacity(0.8)) } } .padding(.horizontal) } }6.3 锁屏视图锁屏视图空间更大可以展示更丰富的信息例如订单号、配送地址和进度条。struct DeliveryLockScreenView: View { let context: ActivityViewContextDeliveryActivityAttributes var body: some View { VStack(alignment: .leading, spacing: 8) { HStack { Text(订单号\(context.attributes.orderNumber)) .font(.caption) Spacer() Text(预计 \(context.state.estimatedArrivalMinutes) 分钟) .font(.caption) } Text(context.state.status) .font(.title2) .fontWeight(.bold) Text(配送至\(context.attributes.deliveryAddress)) .font(.caption) .foregroundColor(.secondary) ProgressView(value: progress) .progressViewStyle(.linear) } .padding() } private var progress: Double { // 根据实际业务计算进度这里简单返回一个示例值 0.6 } }7. 更新 Live Activity当业务状态发生变化时例如骑手取货、配送中、即将送达你需要更新对应的 Live Activity。import ActivityKit func updateDeliveryActivity(activity: ActivityDeliveryActivityAttributes, status: String, minutes: Int) { let updatedState DeliveryActivityAttributes.ContentState( status: status, estimatedArrivalMinutes: minutes ) Task { await activity.update( ActivityContent( state: updatedState, staleDate: Date().addingTimeInterval(60 * 60) ) ) } }更新操作是异步的建议在Task中执行。系统会平滑地过渡到新的状态用户无需任何操作。8. 结束 Live Activity当配送完成或活动不再需要展示时应主动结束 Live Activity释放系统资源。import ActivityKit func endDeliveryActivity(activity: ActivityDeliveryActivityAttributes) { Task { await activity.end( ActivityContent( state: DeliveryActivityAttributes.ContentState( status: 已送达, estimatedArrivalMinutes: 0 ), staleDate: nil ), dismissalPolicy: .immediate ) } }dismissalPolicy支持三种模式.immediate立即移除、.default由系统决定移除时机、.after(date)在指定日期后移除。9. 处理推送更新除了在应用内直接更新Live Activity 还支持通过远程推送APNs更新。这适用于应用不在前台甚至被杀死时的场景。9.1 推送 payload 格式推送 payload 需要包含content-state字段用于传递新的动态状态。{ aps: { timestamp: 1697184000, event: update, content-state: { status: 骑手已取货, estimatedArrivalMinutes: 25 } } }9.2 推送 token 获取在创建 Live Activity 后你需要获取推送 token 并上传到自己的服务器。Task { let pushToken try await activity.pushToken // 将 pushToken 上传到你的服务器 uploadToken(pushToken) }服务器持有该 token 后即可在任意时刻向对应 Live Activity 发送更新推送。10. 注意事项与最佳实践系统限制同一应用同时活跃的 Live Activity 数量有限制通常为 5 个超出后新的创建请求会失败。电量考虑频繁更新会消耗电量建议仅在关键状态变化时更新避免高频轮询。staleDate 设置合理设置staleDate系统会在该时间后自动将活动标记为过期避免展示陈旧信息。灵动岛适配灵动岛视图应保持极简避免过多文字导致截断。权限说明Live Activity 无需用户授权但用户可以在系统设置中手动关闭某个应用的实时活动。测试真机Live Activity 在模拟器上支持有限建议在真机上验证灵动岛和锁屏的实际效果。11. 总结Live Activity 为 iOS 应用提供了一种全新的信息展示方式能够显著提升用户体验。通过 ActivityKit你可以快速实现从创建、更新到结束的完整流程。关键在于合理设计静态属性和动态状态并为灵动岛和锁屏分别构建合适的视图。希望本文能帮助你顺利上手 Live Activity 开发。如果在实践中遇到问题欢迎在评论区交流讨论。

相关新闻

上海普陀区壁挂炉维修|LG壁挂炉维修|机身抖动共振异响预约检查|欧米到家服务热线

上海普陀区壁挂炉维修|LG壁挂炉维修|机身抖动共振异响预约检查|欧米到家服务热线

🔥 壁挂炉是家庭中冬季24小时不间断供暖与供热水的核心设备,一旦突发不点火、不加热、漏水异响或显示屏报错,全家取暖和热水往往立刻受影响。上海家庭使用的壁挂炉品牌繁多,电控逻辑和燃烧结构差异较大。本文系统梳理上海地区壁挂…

2026/10/14 16:53:08 阅读更多 →
Oracle 12c客户端静默安装实战:Linux无GUI环境标准化部署指南

Oracle 12c客户端静默安装实战:Linux无GUI环境标准化部署指南

1. 为什么必须掌握Oracle 12c客户端静默安装——一个被低估的运维基本功在某高校数据库实验室维护一套跨平台教学系统时,我遇到过这样一幕:三台新配的CentOS 7虚拟机需要统一部署Oracle 12c客户端,用于连接远程Oracle RAC集群。现场有位刚入职…

2026/10/14 16:53:08 阅读更多 →
Android Jetpack Room+Paging3列表分页加载实践

Android Jetpack Room+Paging3列表分页加载实践

做客户端开发这些年,最绕不开的一个场景就是列表页。从服务端拉一批数据,塞进 RecyclerView,用户滑到底了再翻下一页,Cache 层再做一次去重合并。这个需求看着简单,落到工程上就会牵扯出数据库写入策略、分页加载状态、…

2026/10/14 16:52:02 阅读更多 →

最新新闻

IntelliJ IDEA 的Qoder CN 插件报错“暂时无法同步代码库索引选择”怎么解决?完整排查与修复指南

IntelliJ IDEA 的Qoder CN 插件报错“暂时无法同步代码库索引选择”怎么解决?完整排查与修复指南

摘要 本文针对在IDEA中使用Qoder CN时出现的报错,给出官方说明与实战解决步骤。官方指出需启用代码库索引:可点击“创建”手动启用,或切换“自动索引”。实战中,先登录Qoder CN且不要输入提示词,再进入设置—>Qode…

2026/10/14 17:36:00 阅读更多 →
PTZ-C8T6.zip 云台控制 C 工程解析:编译、协议与避坑指南

PTZ-C8T6.zip 云台控制 C 工程解析:编译、协议与避坑指南

简介:PTZ-C8T6.zip 是一份面向嵌入式开发初学者与 STM32 学习者的云台控制项目工程源码,基于 STM32F103 系列芯片与 HAL 库构建,适合用于课程设计、毕业设计或电赛类云台控制方案的参考与二次开发。压缩包共 98 个文件,约 675KB&a…

2026/10/14 17:36:00 阅读更多 →
Python 读取 Excel 并写入 zip:自动化报表打包实战

Python 读取 Excel 并写入 zip:自动化报表打包实战

简介:这份资源面向需要处理表格数据的Python学习者与开发者,聚焦Excel文件的读取与写入这一常见任务,帮助解决数据分析、数据清洗与自动化报告中的表格操作问题。压缩包共4个文件,全部为py脚本,整体约6KB,涵…

2026/10/14 17:36:00 阅读更多 →
Terminus(Olares)RabbitMQ 中间件集成实战:用 OlaresManifest.yaml 声明式接入消息队列

Terminus(Olares)RabbitMQ 中间件集成实战:用 OlaresManifest.yaml 声明式接入消息队列

云原生后端运维 【免费下载链接】Terminus Open-Source Personal Cloud OS for Always-On Agents 项目地址: https://gitcode.com/gh_mirrors/terminus2/Terminus 点击查看 免费下载 本篇技术指南基于 Terminus 仓库中 RabbitMQ 集成文档 展开,讲解如何…

2026/10/14 17:36:00 阅读更多 →
九轴姿态解算实战:C语言实现Mahony互补滤波与四元数融合

九轴姿态解算实战:C语言实现Mahony互补滤波与四元数融合

简介:九轴姿态解算源代码是一套面向嵌入式开发、无人机及机器人等场景的C语言实现,融合加速度计、磁力计与陀螺仪数据,用于实时估计物体的横滚、俯仰与偏航角。资源包含4个文件,全部为2个C源文件和2个头文件,压缩包仅5…

2026/10/14 17:36:00 阅读更多 →
C#工业级图形面积周长计算:精度、鲁棒性与性能平衡

C#工业级图形面积周长计算:精度、鲁棒性与性能平衡

1. 项目概述:为什么一个“图形周长、面积计算”功能值得花时间深挖? 你可能第一眼看到“C# 图形周长、面积计算”这个标题,会下意识觉得:“不就是几个数学公式封装成方法吗?勾股定理、πr、底高2……抄一遍就完事。”我…

2026/10/14 17:34:59 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →