使用 RelevanceKit 提升 Apple Watch 上的小组件曝光率。适用于为 watchOS 小组件提供上下文相关性信号、声明基于时间或位置的相关性、组合多个相关性提供者、协助系统在 watchOS 26 上于恰当时机展示正确的小组件,或者在跨 RelevanceKit/WidgetKit/HealthKit/MapKit 的智能叠放(Smart Stack)作用域中进行边界路由调度。
RelevanceKit
在 Apple Watch 智能叠放(Smart Stack)中提供设备端上下文线索,从而提升小组件的显示优先级与曝光率。RelevanceKit 会根据时间、位置、健身状态、作息时间或连接的硬件,告知系统小组件在什么时候具备相关性。适配 Swift 6.3 / watchOS 26+。
Beta 测试阶段提示:在对 RelevanceKit 的可用性或行为做出确定性结论前,请先重新核对 Apple 官方最新文档。
参阅 references/relevancekit-patterns.md 查看完整的相关小组件(relevant-widget)、时间线提供者(timeline provider)、分组、预览及权限配置模式。
目录
概览
watchOS 主要通过两种机制来确定小组件在智能叠放(Smart Stack)中的相关性:
- Timeline provider relevance(时间线提供者相关性) -- 在已有的
AppIntentTimelineProvider上实现relevance()方法,将RelevantContext线索附加到时间线条目(timeline entries)中。跨平台可用;但仅 watchOS 会对这些数据做出响应。 - Relevant widget(相关小组件) -- 结合
RelevanceEntriesProvider使用RelevanceConfiguration,构建完全由相关性线索驱动的小组件。系统会为每个符合相关条件(relevant entry)的条目创建单独的智能叠放卡片。仅支持 watchOS 26+。
当小组件始终有数据展示且相关性仅作为补充辅助时,请选择时间线提供者(timeline provider);当小组件应该仅在条件匹配时才显示,或者需要同时出现多张卡片时(例如显示接下来的多个日历日程),请选择相关小组件(relevant widget)。
核心类型
| 类型 | 模块 | 职责 |
|---|---|---|
RelevantContext |
RelevanceKit | 上下文线索(日期、位置、健身、睡眠、硬件) |
WidgetRelevance |
WidgetKit | 针对某种小组件类型(widget kind)的相关性属性集合 |
WidgetRelevanceAttribute |
WidgetKit | 将小组件配置(widget configuration)与 RelevantContext 进行关联绑定 |
WidgetRelevanceGroup |
WidgetKit | 控制智能叠放中的分组行为 |
RelevanceConfiguration |
WidgetKit | 由相关性线索驱动的小组件配置(watchOS 26+) |
RelevanceEntriesProvider |
WidgetKit | 为基于相关性配置的小组件提供数据条目(watchOS 26+) |
RelevanceEntry |
WidgetKit | 渲染单个相关小组件卡片所需的数据(watchOS 26+) |
RelevanceConfiguration、RelevanceEntriesProvider 和 RelevanceEntry 属于 WidgetKit API。仅当它们作为暴露 RelevanceKit 线索的 watchOS 相关小组件工作流的一部分时,才将它们保留在本 Skill 作用域内。
环境配置
导入模块
import RelevanceKit
import WidgetKit
平台可用性
RelevantContext 虽已支持跨平台声明(iOS 17+、watchOS 10+),但 RelevanceKit 功能仅在 watchOS 上实际生效。在其他平台上调用相关 API 不会产生任何效果。时间线提供者的 relevance() 在 iOS 18+、macOS 15+、visionOS 26+ 和 watchOS 11+ 上可用,便于共享 provider 代码。而 RelevanceConfiguration、RelevanceEntriesProvider 与 RelevanceEntry 仅适用于 watchOS 26+。
权限要求
某些相关性线索需要特定权限或许可配置:
| 相关性线索 | 必需权限 |
|---|---|
.location(inferred:) |
宿主 App(Containing app)申请位置权限;小组件扩展声明 NSWidgetWantsLocation |
.location(_:) (CLRegion) |
宿主 App 申请位置权限;小组件扩展声明 NSWidgetWantsLocation |
.location(category:) |
宿主 App 申请位置权限;小组件扩展声明 NSWidgetWantsLocation |
.fitness(.workoutActive) |
HealthKit 对 HKWorkoutType 的访问权限 |
.fitness(.activityRingsIncomplete) |
HealthKit 对 appleExerciseTime、appleMoveTime 和 appleStandTime 的访问权限 |
.sleep(_:) |
HealthKit 的 sleepAnalysis 权限 |
.hardware(headphones:) |
无需权限 |
.date(...) |
无需权限 |
请务必将位置权限说明字符串(Usage Description)添加到宿主 App 的 Info.plist 中,而不只是小组件扩展。在小组件代码中,在依赖位置线索之前先检查 CLLocationManager.isAuthorizedForWidgetUpdates。对于健身和睡眠线索,请在提供相关性的 App 及小组件扩展 Target 中启用 HealthKit 并申请精确的读取类型。
相关性提供者
方式一:带有相关性支持的时间线提供者
为已有的 AppIntentTimelineProvider 添加 relevance() 方法。这种方式可以在 iOS 和 watchOS 之间共享代码,同时为 watchOS 智能叠放注入智能调度能力。
struct MyProvider: AppIntentTimelineProvider {
// ... snapshot, timeline, placeholder ...
func relevance() async -> WidgetRelevance<MyWidgetIntent> {
let attributes = events.map { event in
let context = RelevantContext.date(
from: event.startDate,
to: event.endDate
)
return WidgetRelevanceAttribute(
configuration: MyWidgetIntent(event: event),
context: context
)
}
return WidgetRelevance(attributes)
}
}
方式二:RelevanceEntriesProvider (watchOS 26+)
构建一个仅在条件匹配时才显现的小组件。系统通过调用 relevance() 来了解小组件何时产生价值,随后用匹配的配置调用 entry() 以获取渲染数据。
@available(watchOS 26.0, *)
struct MyRelevanceProvider: RelevanceEntriesProvider {
func relevance() async -> WidgetRelevance<MyWidgetIntent> {
let attributes = events.map { event in
WidgetRelevanceAttribute(
configuration: MyWidgetIntent(event: event),
context: RelevantContext.date(event.date, kind: .scheduled)
)
}
return WidgetRelevance(attributes)
}
func entry(
configuration: MyWidgetIntent,
context: Context
) async throws -> MyRelevanceEntry {
if context.isPreview {
return .preview
}
return MyRelevanceEntry(event: configuration.event)
}
func placeholder(context: Context) -> MyRelevanceEntry {
.placeholder
}
}
边界路由与职责分工
当某个功能混合使用了小组件、位置、体能训练和智能叠放相关性时,请保持 RelevanceKit 专注于 RelevantContext、WidgetRelevanceAttribute、提供者的 relevance()、RelevantIntentManager、相关小组件接管机制以及相关性线索的权限管理。
将时间线(timelines)、刷新预算(reload budgets)、组件系列(families)、视图渲染(rendering)、APNs 小组件推送、实时活动(Live Activities)和小组件控件(widget Controls)路由分发给 WidgetKit;
将 HKWorkoutSession、HKLiveWorkoutBuilder、HKWorkoutRoute、数据查询、健身记录环/睡眠数据以及授权交互 UX 路由分发给 HealthKit;
将 MKLocalSearch、MKLocalSearchCompleter、MKDirections、地理编码、定位授权、区域(regions)、地理围栏(geofencing)和 POI 地点数据路由分发给 MapKit/CoreLocation。
基于时间的相关性
时间线索告知系统小组件在特定时刻或时间段内具备高相关度。
单一日期
RelevantContext.date(eventDate)
带类型的日期(Date with Kind)
DateKind 提供了关于时间相关性性质的补充提示:
| 类型(Kind) | 适用场景 |
|---|---|
.default |
通用时间相关性 |
.scheduled |
预定日程/预定事件(会议、航班等) |
.informational |
某个时间点附近的相关信息(如天气预报) |
RelevantContext.date(meetingStart, kind: .scheduled)
日期范围
// 使用 from/to
RelevantContext.date(from: startDate, to: endDate)
// 使用 DateInterval
RelevantContext.date(interval: dateInterval, kind: .scheduled)
// 使用 ClosedRange
RelevantContext.date(range: startDate...endDate, kind: .default)
基于位置的相关性
推断位置
系统可以根据用户的日常作息自动推断某些特定位置,无需手动提供坐标。
RelevantContext.location(inferred: .home)
RelevantContext.location(inferred: .work)
RelevantContext.location(inferred: .school)
RelevantContext.location(inferred: .commute)
请按 权限要求 表格配置位置说明,并在返回线索之前检查 CLLocationManager.isAuthorizedForWidgetUpdates。
特定区域
import CoreLocation
let region = CLCircularRegion(
center: CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090),
radius: 500,
identifier: "apple-park"
)
RelevantContext.location(region)
兴趣点类别(Point-of-Interest Category,26.0+ SDK)
指示小组件在指定类别的任何地点附近均具备相关性。若类别不支持则返回 nil。虽然该工厂方法在 Apple 平台的 26.0+ SDK 中均可调用,但 RelevanceKit 线索仍然只在 watchOS 上影响智能叠放行为。
import MapKit
if let context = RelevantContext.location(category: .beach) {
// 只要用户位于沙滩附近,小组件即具备相关性
}
健身与睡眠相关性
健身状态
// 健身记录环未填满时生效
RelevantContext.fitness(.activityRingsIncomplete)
// 进行体能训练(Active Workout)期间生效
RelevantContext.fitness(.workoutActive)
请应用 权限要求 中的精确健身权限映射。
睡眠状态
// 临近就寝时间时生效
RelevantContext.sleep(.bedtime)
// 临近起床时间时生效
RelevantContext.sleep(.wakeup)
请应用 权限要求 中的睡眠权限映射。
硬件相关性
// 耳机连接时生效
RelevantContext.hardware(headphones: .connected)
无需特殊权限。
组合多重信号
在 WidgetRelevance 数组中返回多个 WidgetRelevanceAttribute 值,可使小组件在多种不同条件下都能被判定为具备相关性。
func relevance() async -> WidgetRelevance<MyIntent> {
var attributes: [WidgetRelevanceAttribute<MyIntent>] = []
// 早间通勤时具备相关性
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(mode: .commute),
context: .location(inferred: .commute)
)
)
// 在工作地点具备相关性
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(mode: .work),
context: .location(inferred: .work)
)
)
// 预定日程临近时具备相关性
for event in upcomingEvents {
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(eventID: event.id),
context: .date(event.date, kind: .scheduled)
)
)
}
return WidgetRelevance(attributes)
}
顺序至关重要。 返回的相关性属性请按优先级排序。系统可能只会采用所提供相关性集合的其中一部分子集。
小组件集成
使用 RelevanceConfiguration 构建相关小组件
@available(watchOS 26, *)
struct MyRelevantWidget: Widget {
var body: some WidgetConfiguration {
RelevanceConfiguration(
kind: "com.example.relevant-events",
provider: MyRelevanceProvider()
) { entry in
EventWidgetView(entry: entry)
}
.configurationDisplayName("Events")
.description("Shows upcoming events when relevant")
}
}
与时间线小组件建立关联
当时间线小组件与相关小组件同时展示相同数据时,使用 associatedKind 避免产生重复卡片。系统会替代...
<!-- truncated for translation batch; full body continues in source -->




