2026西湖龙井茶官网DTC发售:茶农直供,政府溯源防伪到农户家
你正在使用另一个应用程序,手机顶部有一个倒计时计时器。你锁定屏幕,同样的计时器依然显示在那里。你向下滑动打开通知中心,它也出现在那里,仍在滴答走动。它看起来像一条通知,但通知是不会滴答走动的。
这就是“实时活动”。它看起来像是三个不同的界面(动态岛、锁屏横幅、通知中心条目),但它们其实是同一个小组件,由操作系统以三种方式渲染。我为自己构建的一款专注计时器应用“Tomoe”接入了这一功能。结论是:只花了一个周末。这个周末的大部分时间都花在摒弃我之前对“实时活动”的错误认知上。一旦理解了其核心结构,代码量其实很少。
本文旨在阐述这一核心结构。
“实时活动”究竟是什么
大多数教程中往往忽略的三点:
它是一个小组件,而非通知。视图代码位于独立于主应用的小组件扩展目标中。应用负责推送状态,扩展负责渲染像素。如果你之前发布过主屏幕小组件,那么原理是一样的。
它由类型化的 ContentState 驱动。你需要声明一个包含“变化内容”的可编码结构体,并使用新实例调用 .update()。不存在通用的“设置任意文本”的应用程序接口。数据结构即契约。
操作系统负责渲染计时器。如果你试图使用 Timer 或每秒更新的 TimelineView,那你就走错路了。斯威夫特用户界面的 Text(timerInterval:countsDown:) 让操作系统为你栅格化倒计时。你的小组件不会每秒唤醒一次。它也无法做到,因为系统资源预算绝不允许。
在任何功能生效之前,需要完成两项基础配置。在应用的 Info.plist 文件中声明 NSSupportsLiveActivities:
<key>NSSupportsLiveActivities</key>
<true/>
……并将部署目标设置为 iOS 16.2 或更高版本。iOS 16.0 和 16.1 中的活动套件界面变动频繁,相关的变通方案不值得投入精力。
数据模型
每个实时活动都由一个 ActivityAttributes 类型作为键值。你需要将其分为“在活动生命周期内固定不变的内容”(即属性本身)和“会发生变化的内容”(即嵌套的 ContentState)。
“Tomoe”的实现如下:
public struct TomoeActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
public var endDate: Date
public var isPaused: Bool
免责声明:本文内容来自互联网,该文观点不代表本站观点。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请到页面底部单击反馈,一经查实,本站将立刻删除。
