Loading...
Loading...
Increase widget visibility on Apple Watch using RelevanceKit. Use when providing contextual relevance signals for watchOS widgets, declaring time-based or location-based relevance, combining multiple relevance providers, or helping the system surface the right widget at the right time on watchOS 26.
npx skill4agent add dpearson2699/swift-ios-skills relevancekitBeta-sensitive. RelevanceKit shipped with watchOS 26. Re-check Apple documentation before making strong claims about API availability or behavior.
relevance()AppIntentTimelineProviderRelevantContextRelevanceConfigurationRelevanceEntriesProvider| Type | Module | Role |
|---|---|---|
| RelevanceKit | A contextual clue (date, location, fitness, sleep, hardware) |
| WidgetKit | Collection of relevance attributes for a widget kind |
| WidgetKit | Pairs a widget configuration with a |
| WidgetKit | Controls grouping behavior in the Smart Stack |
| WidgetKit | Widget configuration driven by relevance clues (watchOS 26+) |
| WidgetKit | Provides entries for a relevance-configured widget (watchOS 26+) |
| WidgetKit | Data needed to render one relevant widget card (watchOS 26+) |
import RelevanceKit
import WidgetKitRelevantContextRelevanceConfigurationRelevanceEntriesProviderRelevanceEntry| Clue | Required Permission |
|---|---|
| Location access |
| Location access |
| Location access |
| HealthKit workout/activity rings permission |
| HealthKit |
| None |
| None |
relevance()AppIntentTimelineProviderstruct 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)
}
}relevance()entry()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
}
}RelevantContext.date(eventDate)DateKind| Kind | Use |
|---|---|
| General time relevance |
| A scheduled event (meeting, flight) |
| Information relevant around a time (weather forecast) |
RelevantContext.date(meetingStart, kind: .scheduled)// Using from/to
RelevantContext.date(from: startDate, to: endDate)
// Using DateInterval
RelevantContext.date(interval: dateInterval, kind: .scheduled)
// Using ClosedRange
RelevantContext.date(range: startDate...endDate, kind: .default)RelevantContext.location(inferred: .home)
RelevantContext.location(inferred: .work)
RelevantContext.location(inferred: .school)
RelevantContext.location(inferred: .commute)import CoreLocation
let region = CLCircularRegion(
center: CLLocationCoordinate2D(latitude: 37.3349, longitude: -122.0090),
radius: 500,
identifier: "apple-park"
)
RelevantContext.location(region)nilimport MapKit
if let context = RelevantContext.location(category: .beach) {
// Widget is relevant whenever the person is near a beach
}// Relevant when activity rings are incomplete
RelevantContext.fitness(.activityRingsIncomplete)
// Relevant during an active workout
RelevantContext.fitness(.workoutActive)// Relevant around bedtime
RelevantContext.sleep(.bedtime)
// Relevant around wakeup
RelevantContext.sleep(.wakeup)sleepAnalysis// Relevant when headphones are connected
RelevantContext.hardware(headphones: .connected)WidgetRelevanceAttributeWidgetRelevancefunc relevance() async -> WidgetRelevance<MyIntent> {
var attributes: [WidgetRelevanceAttribute<MyIntent>] = []
// Relevant during morning commute
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(mode: .commute),
context: .location(inferred: .commute)
)
)
// Relevant at work
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(mode: .work),
context: .location(inferred: .work)
)
)
// Relevant around a scheduled event
for event in upcomingEvents {
attributes.append(
WidgetRelevanceAttribute(
configuration: MyIntent(eventID: event.id),
context: .date(event.date, kind: .scheduled)
)
)
}
return WidgetRelevance(attributes)
}@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")
}
}associatedKindRelevanceConfiguration(
kind: "com.example.relevant-events",
provider: MyRelevanceProvider()
) { entry in
EventWidgetView(entry: entry)
}
.associatedKind("com.example.timeline-events")WidgetRelevanceGroup// Opt out of default per-app grouping so each card appears independently
WidgetRelevanceAttribute(
configuration: intent,
group: .ungrouped
)
// Named group -- only one widget from the group appears at a time
WidgetRelevanceAttribute(
configuration: intent,
group: .named("weather-alerts")
)
// Default system grouping
WidgetRelevanceAttribute(
configuration: intent,
group: .automatic
)RelevantIntentManagerimport AppIntents
func updateRelevantIntents() async {
let intents = events.map { event in
RelevantIntent(
MyWidgetIntent(event: event),
widgetKind: "com.example.events",
relevance: RelevantContext.date(from: event.start, to: event.end)
)
}
try? await RelevantIntentManager.shared.updateRelevantIntents(intents)
}// Preview with sample entries
#Preview("Events", widget: MyRelevantWidget.self, relevanceEntries: {
[EventEntry(event: .surfing), EventEntry(event: .meditation)]
})
// Preview with relevance configurations
#Preview("Relevance", widget: MyRelevantWidget.self, relevance: {
WidgetRelevance([
WidgetRelevanceAttribute(configuration: MyIntent(event: .surfing),
context: .date(Date(), kind: .scheduled))
])
})
// Preview with the full provider
#Preview("Provider", widget: MyRelevantWidget.self,
relevanceProvider: MyRelevanceProvider()).associatedKind(_:)RelevanceEntriesProviderplaceholder(context:)entry(configuration:context:)context.isPreviewupdateRelevantIntentstimeline()location(category:)MKPointOfInterestCategoryimport RelevanceKitimport WidgetKitRelevantContextRelevanceEntriesProviderentryplaceholderrelevancecontext.isPreviewentry(configuration:context:).associatedKind(_:)RelevantIntentManager.updateRelevantIntentslocation(category:)