@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +266 -267
- package/package.json +2 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +68 -68
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,216 +1,222 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: live-activities
|
|
3
|
-
description: "
|
|
3
|
+
description: "ActivityKit Live Activities on the Lock Screen and Dynamic Island: ActivityAttributes and ContentState, request/update/end lifecycle, compact, minimal and expanded layouts, stale dates, push-to-update, push-to-start and channel pushes, update tokens, scheduled starts, ActivityStyle. Use when building, reviewing or improving glanceable live status (delivery tracking, scores, rides, workout timers, media playback) or sending Live Activity APNs payloads. Not for Home Screen or timeline widgets (widgetkit) or generic APNs setup (push-notifications)."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# ActivityKit
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Screen and, on
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
- [Common Mistakes](#common-mistakes)
|
|
38
|
-
- [Review Checklist](#review-checklist)
|
|
39
|
-
- [References](#references)
|
|
8
|
+
# Live Activities (ActivityKit)
|
|
9
|
+
|
|
10
|
+
A Live Activity is a small, time-boxed status card that ActivityKit keeps on the
|
|
11
|
+
Lock Screen and, on hardware that has one, in the Dynamic Island. A paired
|
|
12
|
+
Mac, CarPlay and StandBy may mirror the same card; none of that changes where
|
|
13
|
+
the work lives. The code and the push contract belong here.
|
|
14
|
+
|
|
15
|
+
Boundaries:
|
|
16
|
+
|
|
17
|
+
- Home Screen widgets, `TimelineProvider` and timeline reloads are `widgetkit`
|
|
18
|
+
work. A Live Activity is driven by the ActivityKit lifecycle, not a timeline.
|
|
19
|
+
- APNs auth keys, certificates and app-level remote-notification registration
|
|
20
|
+
are `push-notifications` work.
|
|
21
|
+
- The Live Activity payload itself stays here, even in an answer that routes
|
|
22
|
+
the rest of APNs away. Always state the two invariants:
|
|
23
|
+
- token pushes carry `apns-push-type: liveactivity` and
|
|
24
|
+
`apns-topic: BUNDLE_ID.push-type.liveactivity`;
|
|
25
|
+
- the JSON in `aps.content-state` is decoded with the app's own
|
|
26
|
+
`ActivityAttributes.ContentState` `Codable` conformance, so it has to
|
|
27
|
+
match that shape exactly. `Date` and
|
|
28
|
+
`ClosedRange<Date>` have no universal wire format: do not assume a Unix
|
|
29
|
+
timestamp or a `lowerBound`/`upperBound` object unless the Swift model and
|
|
30
|
+
the server were written to agree on it.
|
|
31
|
+
|
|
32
|
+
Examples target iOS 26 and Swift 6.3. Anything built on `ActivityContent`
|
|
33
|
+
needs iOS 16.2 or later unless a section says otherwise. Longer patterns (a
|
|
34
|
+
full attributes model, server payloads, concurrent activities, state
|
|
35
|
+
observation, errors, testing) are in the
|
|
36
|
+
[patterns reference](references/activitykit-patterns.md).
|
|
40
37
|
|
|
41
38
|
## Workflow
|
|
42
39
|
|
|
43
|
-
###
|
|
40
|
+
### Adding a Live Activity
|
|
44
41
|
|
|
45
|
-
1.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
1. In the main app target's Info.plist, turn on `NSSupportsLiveActivities`
|
|
43
|
+
(`YES`).
|
|
44
|
+
2. Declare an `ActivityAttributes` type with a nested `ContentState`.
|
|
45
|
+
3. In the widget extension's bundle, add an `ActivityConfiguration` that
|
|
46
|
+
supplies the Lock Screen view and the Dynamic Island closures.
|
|
47
|
+
4. Start it: `Activity.request(attributes:content:pushType:)`.
|
|
48
|
+
5. Change it with `activity.update(_:)` and finish it with
|
|
49
|
+
`activity.end(_:dismissalPolicy:)`.
|
|
50
|
+
6. If a server will drive it, send the activity's push token to that server.
|
|
52
51
|
|
|
53
|
-
###
|
|
52
|
+
### Reviewing one
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
Go through the [Review checklist](#review-checklist) item by item.
|
|
56
55
|
|
|
57
|
-
##
|
|
56
|
+
## Modelling the data
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
the
|
|
58
|
+
Two layers, with different lifetimes:
|
|
59
|
+
|
|
60
|
+
- Properties on the attributes struct are fixed for the whole life of the
|
|
61
|
+
activity.
|
|
62
|
+
- `ContentState` carries whatever changes. The entire value is encoded on
|
|
63
|
+
every update and in every push, so keep it lean.
|
|
62
64
|
|
|
63
65
|
```swift
|
|
64
66
|
import ActivityKit
|
|
65
67
|
|
|
66
|
-
struct
|
|
67
|
-
// Static -- set once at activity creation, never changes
|
|
68
|
-
var orderNumber: Int
|
|
69
|
-
var restaurantName: String
|
|
70
|
-
|
|
71
|
-
// Dynamic -- updated throughout the activity lifetime
|
|
68
|
+
struct ChargingAttributes: ActivityAttributes {
|
|
72
69
|
struct ContentState: Codable, Hashable {
|
|
73
|
-
var
|
|
74
|
-
var
|
|
75
|
-
var
|
|
70
|
+
var batteryPercent: Int
|
|
71
|
+
var finishWindow: ClosedRange<Date>
|
|
72
|
+
var phase: ChargePhase
|
|
76
73
|
}
|
|
74
|
+
|
|
75
|
+
var stationName: String
|
|
76
|
+
var connectorLabel: String
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
enum
|
|
80
|
-
case
|
|
79
|
+
enum ChargePhase: String, Codable, Hashable, CaseIterable {
|
|
80
|
+
case queued, connecting, charging, balancing, complete
|
|
81
81
|
|
|
82
|
-
var
|
|
82
|
+
var symbolName: String {
|
|
83
83
|
switch self {
|
|
84
|
-
case .
|
|
85
|
-
case .
|
|
86
|
-
case .
|
|
87
|
-
case .
|
|
88
|
-
case .
|
|
84
|
+
case .queued: "hourglass"
|
|
85
|
+
case .connecting: "powerplug"
|
|
86
|
+
case .charging: "bolt.car"
|
|
87
|
+
case .balancing: "slider.horizontal.3"
|
|
88
|
+
case .complete: "checkmark.circle.fill"
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
### Stale
|
|
94
|
+
### Stale date
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
`ActivityContent` takes a `staleDate`. Once that moment passes without a newer
|
|
97
|
+
update, the system flips `context.isStale` to `true`, and the view should swap
|
|
98
|
+
in a fallback such as a "Refreshing" label instead of showing a number that may
|
|
99
|
+
be wrong.
|
|
97
100
|
|
|
98
101
|
```swift
|
|
99
|
-
let
|
|
102
|
+
let snapshot = ActivityContent(
|
|
100
103
|
state: state,
|
|
101
|
-
staleDate:
|
|
104
|
+
staleDate: .now.addingTimeInterval(5 * 60),
|
|
102
105
|
relevanceScore: 75
|
|
103
106
|
)
|
|
104
107
|
```
|
|
105
108
|
|
|
106
|
-
##
|
|
109
|
+
## Lifecycle
|
|
107
110
|
|
|
108
|
-
###
|
|
111
|
+
### Start
|
|
109
112
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
`Activity.request` creates the activity and puts it on screen. Pass
|
|
114
|
+
`pushType: .token` when a server should be able to update it. The
|
|
115
|
+
`ActivityContent` form of `request` is iOS 16.2+.
|
|
113
116
|
|
|
114
117
|
```swift
|
|
115
|
-
|
|
116
|
-
let
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)
|
|
121
|
-
let content = ActivityContent(state: state, staleDate: nil, relevanceScore: 75)
|
|
122
|
-
|
|
123
|
-
do {
|
|
124
|
-
let activity = try Activity.request(
|
|
125
|
-
attributes: attributes,
|
|
126
|
-
content: content,
|
|
127
|
-
pushType: .token
|
|
118
|
+
func beginCharging(at station: String) {
|
|
119
|
+
let attributes = ChargingAttributes(stationName: station, connectorLabel: "B2")
|
|
120
|
+
let window = Date.now...Date.now.addingTimeInterval(30 * 60)
|
|
121
|
+
let initial = ChargingAttributes.ContentState(
|
|
122
|
+
batteryPercent: 18, finishWindow: window, phase: .connecting
|
|
128
123
|
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
do {
|
|
125
|
+
let activity = try Activity.request(
|
|
126
|
+
attributes: attributes,
|
|
127
|
+
content: ActivityContent(state: initial, staleDate: nil, relevanceScore: 75),
|
|
128
|
+
pushType: .token
|
|
129
|
+
)
|
|
130
|
+
sessionStore.remember(activity.id)
|
|
131
|
+
} catch {
|
|
132
|
+
logger.error("Live Activity refused: \(error.localizedDescription)")
|
|
133
|
+
}
|
|
132
134
|
}
|
|
133
135
|
```
|
|
134
136
|
|
|
135
|
-
###
|
|
137
|
+
### Update
|
|
136
138
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
`await activity.update(content)` changes the card silently. To also light the
|
|
140
|
+
screen with a banner and a sound, use `update(_:alertConfiguration:)`:
|
|
139
141
|
|
|
140
142
|
```swift
|
|
141
|
-
let
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
currentStep: .delivering
|
|
145
|
-
)
|
|
146
|
-
let updatedContent = ActivityContent(
|
|
147
|
-
state: updatedState,
|
|
148
|
-
staleDate: Date().addingTimeInterval(300),
|
|
143
|
+
let next = ActivityContent(
|
|
144
|
+
state: newState,
|
|
145
|
+
staleDate: .now.addingTimeInterval(300),
|
|
149
146
|
relevanceScore: 90
|
|
150
147
|
)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
sound: .default
|
|
160
|
-
))
|
|
148
|
+
await activity.update(
|
|
149
|
+
next,
|
|
150
|
+
alertConfiguration: AlertConfiguration(
|
|
151
|
+
title: "Almost full",
|
|
152
|
+
body: "Battery is at 95 percent.",
|
|
153
|
+
sound: .default
|
|
154
|
+
)
|
|
155
|
+
)
|
|
161
156
|
```
|
|
162
157
|
|
|
163
|
-
###
|
|
158
|
+
### End
|
|
159
|
+
|
|
160
|
+
End the activity when the thing it tracks is over. The dismissal policy decides
|
|
161
|
+
how long the ended card lingers on the Lock Screen:
|
|
164
162
|
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
| Policy | Removal |
|
|
164
|
+
|---|---|
|
|
165
|
+
| `.default` | The system chooses, at most 4 hours later |
|
|
166
|
+
| `.immediate` | Right away |
|
|
167
|
+
| `.after(date)` | At `date`, no later than 4 hours from now |
|
|
167
168
|
|
|
168
169
|
```swift
|
|
169
|
-
let
|
|
170
|
-
|
|
171
|
-
estimatedDeliveryTime: Date()...Date(),
|
|
172
|
-
currentStep: .delivered
|
|
170
|
+
let closing = ChargingAttributes.ContentState(
|
|
171
|
+
batteryPercent: 100, finishWindow: Date.now...Date.now, phase: .complete
|
|
173
172
|
)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
await activity.end(
|
|
174
|
+
ActivityContent(state: closing, staleDate: nil, relevanceScore: 0),
|
|
175
|
+
dismissalPolicy: .after(.now.addingTimeInterval(3600))
|
|
176
|
+
)
|
|
177
|
+
```
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
End on every terminal path, not just the happy one: success, cancellation by
|
|
180
|
+
the user or the app, sign-out or session teardown, an app error you cannot
|
|
181
|
+
recover from, and a terminal failure reported by the server. If the backend
|
|
182
|
+
reports that the tracked event is over or that its status is no longer
|
|
183
|
+
reliable, push or apply a
|
|
184
|
+
final terminal state and end; never leave frozen progress on the Lock Screen.
|
|
181
185
|
|
|
182
|
-
|
|
183
|
-
await activity.end(finalContent, dismissalPolicy: .after(Date().addingTimeInterval(3600)))
|
|
184
|
-
```
|
|
186
|
+
Time limits, which are easy to conflate:
|
|
185
187
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
sooner), system-ended Lock Screen presence (up to 4 additional hours, for 12
|
|
193
|
-
hours total from start), and app-ended `.default` dismissal linger (up to 4 hours
|
|
194
|
-
after ending).
|
|
188
|
+
- The active phase lasts at most 8 hours; the app or the user may end it
|
|
189
|
+
earlier.
|
|
190
|
+
- When the system ends it at that limit, the card may remain on the Lock Screen
|
|
191
|
+
for up to 4 more hours, 12 hours in total from the start.
|
|
192
|
+
- When the app ends it with `.default`, the card can stay visible for as much
|
|
193
|
+
as 4 hours past the end call.
|
|
195
194
|
|
|
196
|
-
## Lock Screen
|
|
195
|
+
## Lock Screen
|
|
197
196
|
|
|
198
|
-
The Lock Screen is the
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
The Lock Screen is the surface that always exists: every device on iOS 16.1 or
|
|
198
|
+
later shows Live Activities there. Lay it out first, then squeeze it into the
|
|
199
|
+
Dynamic Island.
|
|
201
200
|
|
|
202
201
|
```swift
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
ActivityConfiguration(for: DeliveryAttributes.self) { context in
|
|
206
|
-
VStack(alignment: .leading) {
|
|
207
|
-
Text(context.attributes.restaurantName).font(.headline)
|
|
202
|
+
import SwiftUI
|
|
203
|
+
import WidgetKit
|
|
208
204
|
|
|
205
|
+
struct ChargingLiveActivity: Widget {
|
|
206
|
+
var body: some WidgetConfiguration {
|
|
207
|
+
ActivityConfiguration(for: ChargingAttributes.self) { context in
|
|
208
|
+
HStack(spacing: 12) {
|
|
209
|
+
Image(systemName: context.state.phase.symbolName)
|
|
210
|
+
VStack(alignment: .leading) {
|
|
211
|
+
Text(context.attributes.stationName).font(.headline)
|
|
212
|
+
Text("\(context.state.batteryPercent)%")
|
|
213
|
+
}
|
|
214
|
+
Spacer()
|
|
209
215
|
if context.isStale {
|
|
210
|
-
Label("
|
|
216
|
+
Label("Refreshing", systemImage: "arrow.trianglehead.2.clockwise")
|
|
211
217
|
.foregroundStyle(.secondary)
|
|
212
218
|
} else {
|
|
213
|
-
Text(timerInterval: context.state.
|
|
219
|
+
Text(timerInterval: context.state.finishWindow, countsDown: true)
|
|
214
220
|
.monospacedDigit()
|
|
215
221
|
}
|
|
216
222
|
}
|
|
@@ -218,274 +224,226 @@ struct DeliveryActivityWidget: Widget {
|
|
|
218
224
|
} dynamicIsland: { context in
|
|
219
225
|
DynamicIsland {
|
|
220
226
|
DynamicIslandExpandedRegion(.center) {
|
|
221
|
-
Text(context.attributes.
|
|
227
|
+
Text(context.attributes.stationName)
|
|
222
228
|
}
|
|
223
229
|
DynamicIslandExpandedRegion(.trailing) {
|
|
224
|
-
Text(
|
|
230
|
+
Text("\(context.state.batteryPercent)%")
|
|
225
231
|
}
|
|
226
232
|
} compactLeading: {
|
|
227
|
-
Image(systemName: "
|
|
233
|
+
Image(systemName: "bolt.car")
|
|
228
234
|
} compactTrailing: {
|
|
229
|
-
Text(timerInterval: context.state.
|
|
235
|
+
Text(timerInterval: context.state.finishWindow, countsDown: true)
|
|
236
|
+
.monospacedDigit()
|
|
230
237
|
} minimal: {
|
|
231
|
-
Image(systemName: "
|
|
238
|
+
Image(systemName: "bolt.car")
|
|
232
239
|
}
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
242
|
}
|
|
236
243
|
```
|
|
237
244
|
|
|
238
|
-
|
|
245
|
+
Static values come from `context.attributes`; changing values from
|
|
246
|
+
`context.state`.
|
|
239
247
|
|
|
240
|
-
|
|
241
|
-
than roughly 160 points. On iOS 18+, use `supplementalActivityFamilies` when
|
|
242
|
-
you provide adaptive layouts beyond the default: `.medium` for iOS/macOS
|
|
243
|
-
Live Activity sizing and `.small` for watchOS Live Activity sizing.
|
|
248
|
+
### Height and supplemental families
|
|
244
249
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
.supplementalActivityFamilies([.medium, .small])
|
|
252
|
-
```
|
|
250
|
+
The Lock Screen gives a Live Activity little vertical room; keep the layout
|
|
251
|
+
under roughly 160 points. From iOS 18,
|
|
252
|
+
`.supplementalActivityFamilies([.small, .medium])` on the
|
|
253
|
+
`ActivityConfiguration` opts into adaptive sizes: `.medium` is the iPhone and
|
|
254
|
+
Mac size, `.small` the Apple Watch size.
|
|
253
255
|
|
|
254
256
|
## Dynamic Island
|
|
255
257
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
not all devices have a Dynamic Island.
|
|
259
|
-
|
|
260
|
-
### Compact (Leading + Trailing)
|
|
261
|
-
|
|
262
|
-
Used when one Live Activity occupies Dynamic Island compact space. Space is
|
|
263
|
-
extremely limited -- show only the most critical information.
|
|
264
|
-
|
|
265
|
-
| Region | Purpose |
|
|
266
|
-
|---|---|
|
|
267
|
-
| `compactLeading` | Icon or tiny label identifying the activity |
|
|
268
|
-
| `compactTrailing` | One key value (timer, score, status) |
|
|
269
|
-
|
|
270
|
-
### Minimal
|
|
271
|
-
|
|
272
|
-
Shown when multiple Live Activities compete for space. Only one activity gets
|
|
273
|
-
the minimal slot. Display a single icon or glyph.
|
|
274
|
-
|
|
275
|
-
### Expanded Regions
|
|
276
|
-
|
|
277
|
-
Shown when the user long-presses the Dynamic Island.
|
|
258
|
+
Only devices with a Dynamic Island show these presentations. Implement all
|
|
259
|
+
three modes anyway; the Lock Screen remains the main design.
|
|
278
260
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
```swift
|
|
291
|
-
DynamicIsland { /* expanded */ }
|
|
292
|
-
compactLeading: { /* ... */ }
|
|
293
|
-
compactTrailing: { /* ... */ }
|
|
294
|
-
minimal: { /* ... */ }
|
|
295
|
-
.keylineTint(.blue)
|
|
296
|
-
```
|
|
261
|
+
- **Compact**: one Live Activity owns the island. Show the single most
|
|
262
|
+
important fact.
|
|
263
|
+
- `compactLeading`: an icon or a very short label saying what this is.
|
|
264
|
+
- `compactTrailing`: one value, such as a timer, a score or a status.
|
|
265
|
+
- **Minimal**: several Live Activities compete; one of them gets the minimal
|
|
266
|
+
slot. Show a single glyph.
|
|
267
|
+
- **Expanded**: appears on a long press of the island. Regions:
|
|
268
|
+
- `.leading`: the camera's left side; content can wrap below it.
|
|
269
|
+
- `.trailing`: the camera's right side; content can wrap below it.
|
|
270
|
+
- `.center`: directly below the camera.
|
|
271
|
+
- `.bottom`: below everything else.
|
|
297
272
|
|
|
298
|
-
|
|
273
|
+
`.keylineTint(_:)` on the `DynamicIsland` tints the island's outline subtly.
|
|
299
274
|
|
|
300
|
-
|
|
301
|
-
efficient than polling from the app and works when the app is suspended, subject
|
|
302
|
-
to APNs delivery, priority, budget, and throttling.
|
|
275
|
+
## Server-driven updates
|
|
303
276
|
|
|
304
|
-
|
|
277
|
+
APNs pushes are cheaper than having the app poll, and they reach an activity
|
|
278
|
+
while the app is suspended. They are still subject to APNs delivery, priority,
|
|
279
|
+
the system budget and throttling.
|
|
305
280
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
`
|
|
281
|
+
Setup: request with `pushType: .token`, then give the server the update token
|
|
282
|
+
that belongs to this one activity. Tokens rotate, so consume `activity.pushTokenUpdates` (an async
|
|
283
|
+
sequence of `Data`) for the whole life of the activity and re-register every
|
|
284
|
+
value it emits.
|
|
309
285
|
|
|
310
286
|
```swift
|
|
311
|
-
let activity = try Activity.request(
|
|
312
|
-
attributes: attributes,
|
|
313
|
-
content: content,
|
|
314
|
-
pushType: .token
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
// Observe token changes -- tokens can rotate
|
|
318
287
|
Task {
|
|
319
|
-
for await
|
|
320
|
-
let
|
|
321
|
-
try await
|
|
322
|
-
tokenString, activityID: activity.id
|
|
323
|
-
)
|
|
288
|
+
for await tokenData in activity.pushTokenUpdates {
|
|
289
|
+
let hex = tokenData.reduce(into: "") { $0 += String(format: "%02x", $1) }
|
|
290
|
+
try? await backend.registerActivityToken(hex, for: activity.id)
|
|
324
291
|
}
|
|
325
292
|
}
|
|
326
293
|
```
|
|
327
294
|
|
|
328
|
-
###
|
|
295
|
+
### Payload and headers
|
|
329
296
|
|
|
330
|
-
Send an HTTP/2 POST to APNs
|
|
297
|
+
Send an HTTP/2 `POST` to APNs carrying these headers:
|
|
331
298
|
|
|
332
|
-
|
|
333
|
-
- `apns-push-type
|
|
334
|
-
- `apns-
|
|
335
|
-
|
|
299
|
+
- `apns-push-type: liveactivity` (required)
|
|
300
|
+
- `apns-topic: BUNDLE_ID.push-type.liveactivity` (required)
|
|
301
|
+
- `apns-priority: 5` for low priority, or `10` for immediate delivery that
|
|
302
|
+
counts against the budget
|
|
336
303
|
|
|
337
|
-
|
|
338
|
-
|
|
304
|
+
Priority never produces an alert. A visible banner or sound comes only from an
|
|
305
|
+
`aps.alert` object.
|
|
339
306
|
|
|
340
|
-
|
|
307
|
+
Everything sits inside `aps`: `timestamp`, `event`, and the full
|
|
308
|
+
`content-state`.
|
|
341
309
|
|
|
342
|
-
|
|
310
|
+
- `"event": "update"` changes the activity.
|
|
311
|
+
- `"event": "end"` ends it; `dismissal-date` is optional.
|
|
312
|
+
- `"event": "start"` is push-to-start; it adds `attributes-type` and
|
|
313
|
+
`attributes` alongside `content-state`, and `alert` is required.
|
|
314
|
+
- Optional on any event: `stale-date`, `relevance-score`, `alert`.
|
|
343
315
|
|
|
344
|
-
|
|
316
|
+
`content-state` must decode into `ContentState`. With synthesized `Codable`,
|
|
317
|
+
the keys are the property names and the values use the default encodings. If
|
|
318
|
+
the type has custom `CodingKeys` or custom coding, agree on the exact keys and
|
|
319
|
+
value shapes with the server team. A misspelled key, or a number sent as text,
|
|
320
|
+
can be enough for ActivityKit to drop the update.
|
|
345
321
|
|
|
346
|
-
|
|
322
|
+
### Push-to-start (iOS 17.2+)
|
|
347
323
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
try await ServerAPI.shared.registerPushToStartToken(tokenString)
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
```
|
|
324
|
+
A server can start an activity while the app is not running. The token comes
|
|
325
|
+
from the static sequence `Activity<ChargingAttributes>.pushToStartTokenUpdates`.
|
|
326
|
+
It is neither the app's ordinary device token nor any activity's update token;
|
|
327
|
+
store and send it separately.
|
|
356
328
|
|
|
357
|
-
### Frequent
|
|
329
|
+
### Frequent updates
|
|
358
330
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
`ActivityAuthorizationInfo.frequentPushesEnabled` and observe
|
|
362
|
-
`frequentPushEnablementUpdates
|
|
331
|
+
`NSSupportsLiveActivitiesFrequentUpdates = YES` in Info.plist raises the
|
|
332
|
+
system-managed push budget. The user can switch it off, so when cadence
|
|
333
|
+
matters read `ActivityAuthorizationInfo().frequentPushesEnabled` and observe
|
|
334
|
+
`frequentPushEnablementUpdates`. There is no guaranteed update rate; do not
|
|
335
|
+
promise one.
|
|
363
336
|
|
|
364
|
-
##
|
|
337
|
+
## Newer capabilities
|
|
365
338
|
|
|
366
|
-
###
|
|
339
|
+
### ActivityStyle (iOS 18+)
|
|
367
340
|
|
|
368
|
-
|
|
369
|
-
activity automatically without the app being in the foreground. Use for events
|
|
370
|
-
with known start times (sports games, product launches, scheduled deliveries).
|
|
341
|
+
`Activity.request(...style:)` is available from iOS 18, not only iOS 26.
|
|
371
342
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
attributes: attributes,
|
|
379
|
-
content: content,
|
|
380
|
-
pushType: .token,
|
|
381
|
-
style: .standard,
|
|
382
|
-
alertConfiguration: AlertConfiguration(
|
|
383
|
-
title: "Game Starting",
|
|
384
|
-
body: "The live score is ready.",
|
|
385
|
-
sound: .default
|
|
386
|
-
),
|
|
387
|
-
start: scheduledDate
|
|
388
|
-
)
|
|
389
|
-
```
|
|
343
|
+
- `.standard`: for anything that should persist: deliveries, rides, scores,
|
|
344
|
+
timers, order boards.
|
|
345
|
+
- `.transient`: only for brief expanded Dynamic Island moments. The system may
|
|
346
|
+
end it when the device locks, when the expanded view collapses, when the
|
|
347
|
+
user leaves the app, or when the activity would appear outside the Dynamic
|
|
348
|
+
Island.
|
|
390
349
|
|
|
391
|
-
###
|
|
350
|
+
### Scheduled start (iOS 26+)
|
|
392
351
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
short-lived expanded Dynamic Island presentation; it can auto-end when the user
|
|
397
|
-
locks the device, collapses or shrinks the expanded presentation, leaves the
|
|
398
|
-
app, or does other work outside Dynamic Island.
|
|
352
|
+
For events with a known start time (a match, a product launch, a booked
|
|
353
|
+
delivery slot), schedule the activity and let the system start it without the
|
|
354
|
+
app in the foreground:
|
|
399
355
|
|
|
400
356
|
```swift
|
|
357
|
+
guard let kickoff = Calendar.current.date(
|
|
358
|
+
from: DateComponents(year: 2026, month: 11, day: 14, hour: 19, minute: 30)
|
|
359
|
+
) else { return }
|
|
401
360
|
let activity = try Activity.request(
|
|
402
361
|
attributes: attributes,
|
|
403
362
|
content: content,
|
|
404
363
|
pushType: .token,
|
|
405
|
-
style: .standard
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
Live Activities can appear on a paired Mac and on the CarPlay Home Screen. No additional ActivityKit API is required, but validate compact layouts; buttons and toggles in Live Activities do not perform actions in CarPlay.
|
|
412
|
-
|
|
413
|
-
### Channel-Based Push (iOS 18+)
|
|
414
|
-
|
|
415
|
-
Broadcast updates to many Live Activities at once with an APNs-created channel
|
|
416
|
-
ID. Enable the broadcast capability outside Xcode, create the channel on the
|
|
417
|
-
server, then subscribe with `.channel(channelID)`. Channel pushes update or end
|
|
418
|
-
Live Activities; they do not start them. Use `apns-channel-id` and expiration
|
|
419
|
-
for channel pushes instead of the device-token `apns-topic` example above.
|
|
420
|
-
|
|
421
|
-
```swift
|
|
422
|
-
let activity = try Activity.request(
|
|
423
|
-
attributes: attributes, content: content,
|
|
424
|
-
pushType: .channel(channelIDFromServer)
|
|
364
|
+
style: .standard,
|
|
365
|
+
alertConfiguration: AlertConfiguration(
|
|
366
|
+
title: "Match starting", body: "Tap to follow live.", sound: .default
|
|
367
|
+
),
|
|
368
|
+
start: kickoff
|
|
425
369
|
)
|
|
426
370
|
```
|
|
427
371
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
- [ ]
|
|
472
|
-
- [ ]
|
|
473
|
-
- [ ]
|
|
474
|
-
|
|
475
|
-
- [ ]
|
|
476
|
-
|
|
477
|
-
- [ ]
|
|
478
|
-
|
|
479
|
-
- [ ]
|
|
372
|
+
### Paired Mac and CarPlay (iOS 26+)
|
|
373
|
+
|
|
374
|
+
A paired Mac and the CarPlay Home Screen both show Live Activities, and
|
|
375
|
+
ActivityKit needs no additional code for either. Check that the compact layouts read well there.
|
|
376
|
+
Buttons and toggles inside a Live Activity do nothing in CarPlay.
|
|
377
|
+
|
|
378
|
+
### Channel pushes (iOS 18+)
|
|
379
|
+
|
|
380
|
+
One push can update many activities through a channel ID that APNs creates.
|
|
381
|
+
Turn on the broadcast capability for the app in the developer portal (it is not
|
|
382
|
+
an Xcode setting), have the server create the channel, then request with `pushType: .channel(channelID)`. Channel pushes
|
|
383
|
+
update or end activities; they cannot start one. They are addressed with
|
|
384
|
+
`apns-channel-id` and an expiration rather than the device-token `apns-topic`.
|
|
385
|
+
|
|
386
|
+
## Common mistakes
|
|
387
|
+
|
|
388
|
+
1. A crowded compact view. One icon and one value is the budget.
|
|
389
|
+
2. Updating from the app too often, which drains battery. Let the server push
|
|
390
|
+
its own changes; update locally only in response to user actions.
|
|
391
|
+
3. Forgetting to end on some terminal path. A leftover activity is a bug the
|
|
392
|
+
user has to clear by hand.
|
|
393
|
+
4. Designing for the Dynamic Island first. Many devices have none; the Lock
|
|
394
|
+
Screen is primary.
|
|
395
|
+
5. Treating a Live Activity as a Home Screen widget with a timeline. Use the
|
|
396
|
+
ActivityKit lifecycle; send timeline widgets to `widgetkit`.
|
|
397
|
+
6. Reducing payload guidance to "match the content-state". State the real
|
|
398
|
+
`ContentState` `Codable` contract and the `Date` / `ClosedRange<Date>`
|
|
399
|
+
caveat; only the generic APNs pieces (auth keys, registration) move to
|
|
400
|
+
`push-notifications`.
|
|
401
|
+
7. Sensitive values in attributes or state. The card is readable on a locked
|
|
402
|
+
phone; show a safe summary.
|
|
403
|
+
8. Ignoring `staleDate`. Check `context.isStale` and render a fallback.
|
|
404
|
+
9. Registering the update token once. It can change at any time; re-send it on
|
|
405
|
+
every `pushTokenUpdates` value.
|
|
406
|
+
10. `NSSupportsLiveActivities` placed in the extension target's plist. The key
|
|
407
|
+
is read from the main app.
|
|
408
|
+
11. The deprecated `contentState:` variants of request, update and end. Use
|
|
409
|
+
`ActivityContent` throughout.
|
|
410
|
+
12. Network or location work inside Live Activity views. Compute it in the app
|
|
411
|
+
or on the server and deliver the result through an update or a push.
|
|
412
|
+
|
|
413
|
+
## Review checklist
|
|
414
|
+
|
|
415
|
+
- [ ] `ActivityAttributes` separates static properties from `ContentState`
|
|
416
|
+
- [ ] Host app Info.plist has `NSSupportsLiveActivities = YES`
|
|
417
|
+
- [ ] Request, update and end use `ActivityContent`, not the deprecated
|
|
418
|
+
`contentState` API
|
|
419
|
+
- [ ] Activity ends on success, error, cancellation, sign-out and terminal
|
|
420
|
+
server failure
|
|
421
|
+
- [ ] ActivityKit lifecycle and surfaces are kept apart from Home Screen or
|
|
422
|
+
timeline widget code
|
|
423
|
+
- [ ] Lock Screen view handles `context.isStale`
|
|
424
|
+
- [ ] Compact, expanded and minimal Dynamic Island modes exist, with the Lock
|
|
425
|
+
Screen as the fallback
|
|
426
|
+
- [ ] Update token forwarded from `activity.pushTokenUpdates`
|
|
427
|
+
- [ ] Push-to-start token collected from
|
|
428
|
+
`Activity<Attributes>.pushToStartTokenUpdates`
|
|
429
|
+
- [ ] Push-to-start payload carries `alert`
|
|
430
|
+
- [ ] `content-state` JSON matches the real `ContentState` coding, including an
|
|
431
|
+
agreed date and range encoding
|
|
432
|
+
- [ ] Durations are stated separately: 8 h active, 12 h total after a system
|
|
433
|
+
end, 4 h linger after an app end with `.default`
|
|
480
434
|
- [ ] `ActivityAuthorizationInfo` checked before starting
|
|
481
|
-
- [ ] `frequentPushesEnabled` checked before
|
|
482
|
-
- [ ] ContentState
|
|
483
|
-
- [ ]
|
|
484
|
-
- [ ]
|
|
485
|
-
|
|
486
|
-
- [ ]
|
|
487
|
-
- [ ]
|
|
435
|
+
- [ ] `frequentPushesEnabled` checked before relying on high-cadence pushes
|
|
436
|
+
- [ ] `ContentState` is small
|
|
437
|
+
- [ ] `style:`, `.channel` and supplemental families are gated on iOS 18
|
|
438
|
+
- [ ] Each `style:` choice is justified: `.standard` for persistent,
|
|
439
|
+
`.transient` only for short expanded moments
|
|
440
|
+
- [ ] Push priority and `aps.alert` are handled as separate concerns
|
|
441
|
+
- [ ] Views do no network or location work
|
|
442
|
+
- [ ] Push delivery and Dynamic Island tested on a real device
|
|
488
443
|
|
|
489
444
|
## References
|
|
490
445
|
|
|
491
|
-
-
|
|
446
|
+
- [ActivityKit patterns](references/activitykit-patterns.md): complete
|
|
447
|
+
attributes model, start/update/end variants, server payloads and headers, channel pushes, concurrent activities, state and token observation,
|
|
448
|
+
authorization, errors, background behaviour, testing, Info.plist keys and
|
|
449
|
+
documentation links.
|