@mmerterden/multi-agent-pipeline 20.6.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 +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- 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/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- 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/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- 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/ci-cd-pipelines/SKILL.md +1 -0
- 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/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- 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/council/SKILL.md +1 -0
- 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/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- 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/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- 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/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- 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-coding-standard/SKILL.md +1 -0
- 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-module-structure/SKILL.md +1 -0
- 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-security/SKILL.md +2 -0
- 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/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- 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/nextjs-app-router/SKILL.md +1 -0
- 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/play-store-review/SKILL.md +2 -0
- 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/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- 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/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- 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/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- 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/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- 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/typescript-patterns/SKILL.md +1 -0
- 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/vue-composition/SKILL.md +1 -0
- 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/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- 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,429 +1,357 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: widgetkit
|
|
3
|
-
description: "
|
|
3
|
+
description: "WidgetKit and ActivityKit surfaces on iOS 26+: timeline-driven widgets for the Home Screen, the Lock Screen and StandBy, interactive widgets using Button or Toggle with AppIntent actions, Live Activities and their Dynamic Island layouts (compact, expanded, minimal), Control Center controls with ControlWidgetButton or ControlWidgetToggle, families, deep links, the refresh budget, reloads triggered by push, Liquid Glass accented rendering, extension setup, App Groups and entitlements. Use when implementing, reviewing or improving widgets, Live Activities or controls."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# WidgetKit
|
|
8
|
+
# WidgetKit
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
Widgets are small SwiftUI snapshots that the system renders from data your
|
|
11
|
+
extension hands it ahead of time. This skill targets iOS 26+ and covers every
|
|
12
|
+
surface WidgetKit and ActivityKit draw on: the Home Screen, the Lock Screen,
|
|
13
|
+
Live Activities and the Dynamic Island, Control Center and StandBy.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
Related skills: `app-intents` for intent and entity design beyond what a widget
|
|
16
|
+
needs, `live-activities` for deeper ActivityKit push contracts.
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Longer examples are in [the advanced reference](references/widgetkit-advanced.md).
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
- [Widget Protocol and WidgetBundle](#widget-protocol-and-widgetbundle)
|
|
20
|
-
- [Configuration Types](#configuration-types)
|
|
21
|
-
- [TimelineProvider](#timelineprovider)
|
|
22
|
-
- [AppIntentTimelineProvider](#appintenttimelineprovider)
|
|
23
|
-
- [Widget Families](#widget-families)
|
|
24
|
-
- [Interactive Widgets (iOS 17+)](#interactive-widgets-ios-17)
|
|
25
|
-
- [Live Activities and Dynamic Island](#live-activities-and-dynamic-island)
|
|
26
|
-
- [Control Center Widgets (iOS 18+)](#control-center-widgets-ios-18)
|
|
27
|
-
- [Lock Screen Widgets](#lock-screen-widgets)
|
|
28
|
-
- [StandBy Mode](#standby-mode)
|
|
29
|
-
- [Design Patterns](#design-patterns)
|
|
30
|
-
- [iOS 26 Additions](#ios-26-additions)
|
|
31
|
-
- [Common Mistakes](#common-mistakes)
|
|
32
|
-
- [Review Checklist](#review-checklist)
|
|
33
|
-
- [References](#references)
|
|
20
|
+
## Workflows
|
|
34
21
|
|
|
35
|
-
|
|
22
|
+
### New widget
|
|
36
23
|
|
|
37
|
-
|
|
24
|
+
1. In Xcode choose File > New > Target > Widget Extension.
|
|
25
|
+
2. Turn on App Groups for both the app and the extension so they can share data.
|
|
26
|
+
3. Write a `TimelineEntry` type: a `date` plus whatever the view shows.
|
|
27
|
+
4. Write a provider: `TimelineProvider` for a fixed widget,
|
|
28
|
+
`AppIntentTimelineProvider` for a configurable one.
|
|
29
|
+
5. Write the SwiftUI view and let it adapt to the current `WidgetFamily`.
|
|
30
|
+
6. Declare a `Widget` type with its configuration and supported families.
|
|
31
|
+
7. List every widget in one `WidgetBundle` and put `@main` on the bundle.
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
2. Enable App Groups for shared data between the app and widget extension.
|
|
41
|
-
3. Define a `TimelineEntry` struct with a `date` property and display data.
|
|
42
|
-
4. Implement a `TimelineProvider` (static) or `AppIntentTimelineProvider` (configurable).
|
|
43
|
-
5. Build the widget view using SwiftUI, adapting layout per `WidgetFamily`.
|
|
44
|
-
6. Declare the `Widget` conforming struct with a configuration and supported families.
|
|
45
|
-
7. Register all widgets in a `WidgetBundle` annotated with `@main`.
|
|
33
|
+
### Live Activity
|
|
46
34
|
|
|
47
|
-
|
|
35
|
+
1. Declare `ActivityAttributes` with a nested `ContentState`.
|
|
36
|
+
2. Set `NSSupportsLiveActivities` to `YES` in the main app's Info.plist.
|
|
37
|
+
3. Add an `ActivityConfiguration` to the widget bundle with the Lock Screen view
|
|
38
|
+
and the Dynamic Island closures.
|
|
39
|
+
4. `Activity.request(attributes:content:pushType:)` starts it,
|
|
40
|
+
`activity.update(_:)` changes it and `activity.end(_:dismissalPolicy:)` closes it.
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
2. Add `NSSupportsLiveActivities = YES` to the app's Info.plist.
|
|
51
|
-
3. Create an `ActivityConfiguration` in the widget bundle with Lock Screen content
|
|
52
|
-
and Dynamic Island closures.
|
|
53
|
-
4. Start the activity with `Activity.request(attributes:content:pushType:)`.
|
|
54
|
-
5. Update with `activity.update(_:)` and end with `activity.end(_:dismissalPolicy:)`.
|
|
42
|
+
### Control Center control
|
|
55
43
|
|
|
56
|
-
|
|
44
|
+
1. Write the `AppIntent` the control runs.
|
|
45
|
+
2. Build a `ControlWidgetButton` or `ControlWidgetToggle`.
|
|
46
|
+
3. Wrap it in `StaticControlConfiguration` or `AppIntentControlConfiguration`.
|
|
57
47
|
|
|
58
|
-
|
|
59
|
-
2. Create a `ControlWidgetButton` or `ControlWidgetToggle` in the widget bundle.
|
|
60
|
-
3. Use `StaticControlConfiguration` or `AppIntentControlConfiguration`.
|
|
48
|
+
### Review
|
|
61
49
|
|
|
62
|
-
|
|
50
|
+
Go through the [checklist](#review-checklist) below.
|
|
63
51
|
|
|
64
|
-
|
|
52
|
+
## Widget and WidgetBundle
|
|
65
53
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Every widget conforms to the `Widget` protocol and returns a `WidgetConfiguration`
|
|
71
|
-
from its `body`.
|
|
54
|
+
A widget is a type conforming to `Widget`. Its `body` returns a
|
|
55
|
+
`WidgetConfiguration`, and it carries a `kind` string that identifies it for
|
|
56
|
+
reloads.
|
|
72
57
|
|
|
73
58
|
```swift
|
|
74
|
-
struct
|
|
75
|
-
let kind
|
|
59
|
+
struct TideWidget: Widget {
|
|
60
|
+
let kind = "TideWidget"
|
|
76
61
|
|
|
77
62
|
var body: some WidgetConfiguration {
|
|
78
|
-
StaticConfiguration(kind: kind, provider:
|
|
79
|
-
|
|
63
|
+
StaticConfiguration(kind: kind, provider: TideProvider()) { entry in
|
|
64
|
+
TideView(entry: entry)
|
|
80
65
|
}
|
|
81
|
-
.configurationDisplayName("
|
|
82
|
-
.description("
|
|
66
|
+
.configurationDisplayName("Tides")
|
|
67
|
+
.description("Next high and low water at your beach.")
|
|
83
68
|
.supportedFamilies([.systemSmall, .systemMedium])
|
|
84
69
|
}
|
|
85
70
|
}
|
|
86
|
-
```
|
|
87
71
|
|
|
88
|
-
### WidgetBundle
|
|
89
|
-
|
|
90
|
-
Use `WidgetBundle` to expose multiple widgets from a single extension.
|
|
91
|
-
|
|
92
|
-
```swift
|
|
93
72
|
@main
|
|
94
|
-
struct
|
|
73
|
+
struct HarborWidgets: WidgetBundle {
|
|
95
74
|
var body: some Widget {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
QuickActionControl() // Control Center
|
|
75
|
+
TideWidget()
|
|
76
|
+
HarborActivityWidget()
|
|
77
|
+
LighthouseControl()
|
|
100
78
|
}
|
|
101
79
|
}
|
|
102
80
|
```
|
|
103
81
|
|
|
104
|
-
|
|
82
|
+
One `WidgetBundle` can expose ordinary widgets, Live Activity widgets and
|
|
83
|
+
Control Center controls from the same extension.
|
|
105
84
|
|
|
106
|
-
|
|
107
|
-
(recommended) for configurable widgets paired with `AppIntentTimelineProvider`.
|
|
85
|
+
## Configuration Types
|
|
108
86
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
StaticConfiguration
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
// Configurable
|
|
115
|
-
AppIntentConfiguration(kind: "ConfigWidget", intent: SelectCategoryIntent.self,
|
|
116
|
-
provider: CategoryProvider()) { entry in
|
|
117
|
-
CategoryWidgetView(entry: entry)
|
|
118
|
-
}
|
|
119
|
-
```
|
|
87
|
+
| Type | Use |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `StaticConfiguration` | Widget with no user settings |
|
|
90
|
+
| `AppIntentConfiguration(kind:intent:provider:)` | Preferred for configurable widgets; pairs with `AppIntentTimelineProvider` |
|
|
120
91
|
|
|
121
|
-
|
|
92
|
+
Modifiers shared by both:
|
|
122
93
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
| `.supportedFamilies(_:)` | Array of `WidgetFamily` values |
|
|
128
|
-
| `.supplementalActivityFamilies(_:)` | Live Activity sizes (`.small`, `.medium`) |
|
|
94
|
+
- `.configurationDisplayName(_:)`: title shown in the widget gallery.
|
|
95
|
+
- `.description(_:)`: gallery blurb.
|
|
96
|
+
- `.supportedFamilies(_:)`: the `WidgetFamily` cases you support.
|
|
97
|
+
- `.supplementalActivityFamilies(_:)`: extra Live Activity sizes, `.small` and `.medium`.
|
|
129
98
|
|
|
130
99
|
## TimelineProvider
|
|
131
100
|
|
|
132
|
-
For
|
|
101
|
+
For fixed widgets. It uses completion handlers and needs three methods.
|
|
133
102
|
|
|
134
103
|
```swift
|
|
135
|
-
struct
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
func placeholder(in context: Context) -> WeatherEntry {
|
|
139
|
-
WeatherEntry(date: .now, temperature: 72, condition: "Sunny")
|
|
104
|
+
struct TideProvider: TimelineProvider {
|
|
105
|
+
func placeholder(in context: Context) -> TideEntry {
|
|
106
|
+
.sample
|
|
140
107
|
}
|
|
141
108
|
|
|
142
|
-
func getSnapshot(in context: Context, completion: @escaping (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
109
|
+
func getSnapshot(in context: Context, completion: @escaping @Sendable (TideEntry) -> Void) {
|
|
110
|
+
if context.isPreview {
|
|
111
|
+
completion(.sample)
|
|
112
|
+
} else {
|
|
113
|
+
completion(TideStore.shared.latestEntry())
|
|
114
|
+
}
|
|
147
115
|
}
|
|
148
116
|
|
|
149
|
-
func getTimeline(in context: Context, completion: @escaping (Timeline<
|
|
117
|
+
func getTimeline(in context: Context, completion: @escaping @Sendable (Timeline<TideEntry>) -> Void) {
|
|
150
118
|
Task {
|
|
151
|
-
let
|
|
152
|
-
let
|
|
153
|
-
let
|
|
154
|
-
completion(Timeline(entries: [
|
|
119
|
+
let reading = await TideStore.shared.loadReading()
|
|
120
|
+
let current = TideEntry(date: .now, reading: reading)
|
|
121
|
+
let refresh = Calendar.current.date(byAdding: .minute, value: 60, to: .now) ?? .now
|
|
122
|
+
completion(Timeline(entries: [current], policy: .after(refresh)))
|
|
155
123
|
}
|
|
156
124
|
}
|
|
157
125
|
}
|
|
158
126
|
```
|
|
159
127
|
|
|
128
|
+
`placeholder(in:)` hands back sample data instantly. The snapshot shows sample
|
|
129
|
+
data when `context.isPreview` is true and real data otherwise. The protocol
|
|
130
|
+
declares both completion handlers `@Sendable`; keep that in the signature, or
|
|
131
|
+
Swift 6 rejects handing `completion` to the `Task` as a data race.
|
|
132
|
+
|
|
160
133
|
## AppIntentTimelineProvider
|
|
161
134
|
|
|
162
|
-
For configurable widgets.
|
|
135
|
+
For configurable widgets. It is async/await from the start and receives the
|
|
136
|
+
user's intent.
|
|
163
137
|
|
|
164
138
|
```swift
|
|
165
|
-
struct
|
|
166
|
-
typealias Entry =
|
|
167
|
-
typealias Intent =
|
|
139
|
+
struct BeachProvider: AppIntentTimelineProvider {
|
|
140
|
+
typealias Entry = TideEntry
|
|
141
|
+
typealias Intent = PickBeachIntent
|
|
168
142
|
|
|
169
|
-
func placeholder(in context: Context) ->
|
|
170
|
-
CategoryEntry(date: .now, categoryName: "Sample", items: [])
|
|
171
|
-
}
|
|
143
|
+
func placeholder(in context: Context) -> TideEntry { .sample }
|
|
172
144
|
|
|
173
|
-
func snapshot(for
|
|
174
|
-
|
|
175
|
-
return CategoryEntry(date: .now, categoryName: config.category.name, items: items)
|
|
145
|
+
func snapshot(for configuration: PickBeachIntent, in context: Context) async -> TideEntry {
|
|
146
|
+
context.isPreview ? .sample : await TideStore.shared.entry(for: configuration.beach)
|
|
176
147
|
}
|
|
177
148
|
|
|
178
|
-
func timeline(for
|
|
179
|
-
let
|
|
180
|
-
|
|
181
|
-
return Timeline(entries: [entry], policy: .atEnd)
|
|
149
|
+
func timeline(for configuration: PickBeachIntent, in context: Context) async -> Timeline<TideEntry> {
|
|
150
|
+
let latest = await TideStore.shared.entry(for: configuration.beach)
|
|
151
|
+
return Timeline(entries: [latest], policy: .atEnd)
|
|
182
152
|
}
|
|
183
153
|
}
|
|
184
154
|
```
|
|
185
155
|
|
|
186
156
|
## Widget Families
|
|
187
157
|
|
|
188
|
-
| Family |
|
|
158
|
+
| Family | Where it runs |
|
|
189
159
|
|---|---|
|
|
190
|
-
| `.systemSmall` | iOS, iPadOS, macOS, CarPlay
|
|
191
|
-
| `.systemMedium` | iOS, iPadOS, macOS |
|
|
192
|
-
| `.systemLarge` | iOS, iPadOS, macOS |
|
|
160
|
+
| `.systemSmall` | iOS, iPadOS, macOS, and CarPlay from iOS 26 |
|
|
161
|
+
| `.systemMedium`, `.systemLarge` | iOS, iPadOS, macOS |
|
|
193
162
|
| `.systemExtraLarge` | iPadOS only |
|
|
194
|
-
| `.accessoryCircular` | iOS, watchOS |
|
|
195
|
-
| `.accessoryRectangular` | iOS, watchOS |
|
|
196
|
-
| `.accessoryInline` | iOS, watchOS |
|
|
163
|
+
| `.accessoryCircular`, `.accessoryRectangular`, `.accessoryInline` | iOS, watchOS |
|
|
197
164
|
| `.accessoryCorner` | watchOS only |
|
|
198
165
|
|
|
199
|
-
Adapt layout per family using `@Environment(\.widgetFamily)`:
|
|
200
|
-
|
|
201
166
|
```swift
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
167
|
+
struct TideView: View {
|
|
168
|
+
@Environment(\.widgetFamily) private var family
|
|
169
|
+
let entry: TideEntry
|
|
170
|
+
|
|
171
|
+
var body: some View {
|
|
172
|
+
switch family {
|
|
173
|
+
case .accessoryInline: Text(entry.reading.shortLine)
|
|
174
|
+
case .systemMedium: TideChartRow(entry: entry)
|
|
175
|
+
default: TideSummary(entry: entry)
|
|
176
|
+
}
|
|
210
177
|
}
|
|
211
178
|
}
|
|
212
179
|
```
|
|
213
180
|
|
|
214
181
|
## Interactive Widgets (iOS 17+)
|
|
215
182
|
|
|
216
|
-
|
|
217
|
-
|
|
183
|
+
`Button` and `Toggle` that take an `AppIntent` run the action inside the widget
|
|
184
|
+
without opening the app.
|
|
218
185
|
|
|
219
186
|
```swift
|
|
220
|
-
struct
|
|
221
|
-
static
|
|
222
|
-
|
|
187
|
+
struct WaterPlantIntent: AppIntent {
|
|
188
|
+
static let title: LocalizedStringResource = "Water Plant"
|
|
189
|
+
|
|
190
|
+
@Parameter(title: "Plant")
|
|
191
|
+
var plantID: String
|
|
192
|
+
|
|
193
|
+
init() {}
|
|
194
|
+
init(plantID: String) { self.plantID = plantID }
|
|
223
195
|
|
|
224
196
|
func perform() async throws -> some IntentResult {
|
|
225
|
-
await
|
|
197
|
+
await PlantLog.shared.recordWatering(plantID)
|
|
226
198
|
return .result()
|
|
227
199
|
}
|
|
228
200
|
}
|
|
229
201
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
Image(systemName: entry.isFavorite ? "star.fill" : "star")
|
|
202
|
+
Button(intent: WaterPlantIntent(plantID: plant.id)) {
|
|
203
|
+
Image(systemName: "drop.fill")
|
|
233
204
|
}
|
|
234
205
|
```
|
|
235
206
|
|
|
236
207
|
## Live Activities and Dynamic Island
|
|
237
208
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
Define the static and dynamic data model.
|
|
209
|
+
Fields that never change go on the `ActivityAttributes` type; changing fields go
|
|
210
|
+
on its nested `ContentState`, which must be `Codable` and `Hashable`.
|
|
241
211
|
|
|
242
212
|
```swift
|
|
243
|
-
struct
|
|
213
|
+
struct RepairAttributes: ActivityAttributes {
|
|
244
214
|
struct ContentState: Codable, Hashable {
|
|
245
|
-
var
|
|
246
|
-
var
|
|
247
|
-
var currentStep: DeliveryStep
|
|
215
|
+
var window: ClosedRange<Date>
|
|
216
|
+
var stage: RepairStage
|
|
248
217
|
}
|
|
249
|
-
|
|
250
|
-
var orderNumber: Int
|
|
251
|
-
var restaurantName: String
|
|
218
|
+
var ticketNumber: String
|
|
252
219
|
}
|
|
253
220
|
```
|
|
254
221
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
`ActivityConfiguration(for:)` body returns the Lock Screen view; its
|
|
259
|
-
`dynamicIsland` closure declares the expanded regions plus `compactLeading`,
|
|
260
|
-
`compactTrailing`, and `minimal`. See [references/widgetkit-advanced.md](references/widgetkit-advanced.md)
|
|
261
|
-
("Live Activity Full ActivityConfiguration Example") for a complete implementation.
|
|
222
|
+
`ActivityConfiguration(for:)` takes the Lock Screen view in its main closure
|
|
223
|
+
and a `dynamicIsland` closure that declares the expanded regions plus
|
|
224
|
+
`compactLeading`, `compactTrailing` and `minimal`.
|
|
262
225
|
|
|
263
|
-
|
|
226
|
+
Expanded regions:
|
|
264
227
|
|
|
265
|
-
| Region |
|
|
228
|
+
| Region | Placement |
|
|
266
229
|
|---|---|
|
|
267
|
-
| `.leading` |
|
|
268
|
-
| `.trailing` |
|
|
269
|
-
| `.center` |
|
|
270
|
-
| `.bottom` |
|
|
230
|
+
| `.leading` | Beside the TrueDepth camera on its left, continuing below |
|
|
231
|
+
| `.trailing` | Beside the camera on its right, continuing below |
|
|
232
|
+
| `.center` | Right under the camera |
|
|
233
|
+
| `.bottom` | Under every other region |
|
|
271
234
|
|
|
272
|
-
|
|
235
|
+
Lifecycle:
|
|
273
236
|
|
|
274
237
|
```swift
|
|
275
|
-
let
|
|
276
|
-
let
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
238
|
+
let initial = RepairAttributes.ContentState(window: start...finish, stage: .diagnosing)
|
|
239
|
+
let opening = ActivityContent(state: initial, staleDate: finish, relevanceScore: 75)
|
|
240
|
+
let activity = try Activity.request(
|
|
241
|
+
attributes: RepairAttributes(ticketNumber: "R-2291"),
|
|
242
|
+
content: opening,
|
|
243
|
+
pushType: .token
|
|
280
244
|
)
|
|
281
|
-
let content = ActivityContent(state: state, staleDate: nil, relevanceScore: 75)
|
|
282
|
-
let activity = try Activity.request(attributes: attributes, content: content, pushType: .token)
|
|
283
245
|
|
|
284
|
-
let
|
|
285
|
-
await activity.update(
|
|
246
|
+
let next = ActivityContent(state: updatedState, staleDate: finish, relevanceScore: 90)
|
|
247
|
+
await activity.update(next)
|
|
286
248
|
|
|
287
|
-
let
|
|
288
|
-
await activity.end(
|
|
249
|
+
let done = ActivityContent(state: closedState, staleDate: nil, relevanceScore: 0)
|
|
250
|
+
await activity.end(done, dismissalPolicy: .after(.now.addingTimeInterval(1800)))
|
|
289
251
|
```
|
|
290
252
|
|
|
253
|
+
A complete configuration with every region is in
|
|
254
|
+
[Live Activity Full ActivityConfiguration Example](references/widgetkit-advanced.md#live-activity-full-activityconfiguration-example).
|
|
255
|
+
|
|
291
256
|
## Control Center Widgets (iOS 18+)
|
|
292
257
|
|
|
293
|
-
|
|
294
|
-
`StaticControlConfiguration`
|
|
295
|
-
|
|
258
|
+
Put a `ControlWidgetButton` or `ControlWidgetToggle` inside
|
|
259
|
+
`StaticControlConfiguration` or `AppIntentControlConfiguration`. Every control
|
|
260
|
+
performs an `AppIntent`.
|
|
296
261
|
|
|
297
262
|
```swift
|
|
298
|
-
struct
|
|
263
|
+
struct LighthouseControl: ControlWidget {
|
|
299
264
|
var body: some ControlWidgetConfiguration {
|
|
300
|
-
StaticControlConfiguration(kind: "
|
|
301
|
-
ControlWidgetButton(action:
|
|
302
|
-
Label("
|
|
265
|
+
StaticControlConfiguration(kind: "LighthouseControl") {
|
|
266
|
+
ControlWidgetButton(action: FlashBeaconIntent()) {
|
|
267
|
+
Label("Beacon", systemImage: "light.beacon.max")
|
|
303
268
|
}
|
|
304
269
|
}
|
|
305
|
-
.displayName("
|
|
270
|
+
.displayName("Flash Beacon")
|
|
306
271
|
}
|
|
307
272
|
}
|
|
308
273
|
```
|
|
309
274
|
|
|
310
|
-
|
|
311
|
-
|
|
275
|
+
A toggle with live state is in
|
|
276
|
+
[Control Center Control Examples](references/widgetkit-advanced.md#control-center-control-examples).
|
|
312
277
|
|
|
313
278
|
## Lock Screen Widgets
|
|
314
279
|
|
|
315
|
-
Use accessory families (
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
(
|
|
319
|
-
"AccessoryWidgetBackground" for rendering-mode adaptation.
|
|
280
|
+
Use the accessory families and put `AccessoryWidgetBackground()` behind the
|
|
281
|
+
content for the system's translucent backing. See
|
|
282
|
+
[Lock Screen Accessory Widget Example](references/widgetkit-advanced.md#lock-screen-accessory-widget-example)
|
|
283
|
+
and [AccessoryWidgetBackground](references/widgetkit-advanced.md#accessorywidgetbackground).
|
|
320
284
|
|
|
321
285
|
## StandBy Mode
|
|
322
286
|
|
|
323
|
-
`.systemSmall` widgets
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
```swift
|
|
327
|
-
@Environment(\.widgetLocation) var location
|
|
328
|
-
// location == .standBy, .homeScreen, .lockScreen, .carPlay, etc.
|
|
329
|
-
```
|
|
287
|
+
`.systemSmall` widgets show up in StandBy automatically when an iPhone charges
|
|
288
|
+
on its side. Read `@Environment(\.widgetLocation)` to tell where you are drawn:
|
|
289
|
+
`.homeScreen`, `.lockScreen`, `.standBy` or `.carPlay`.
|
|
330
290
|
|
|
331
291
|
## Design Patterns
|
|
332
292
|
|
|
333
|
-
-
|
|
334
|
-
Lock Screen
|
|
335
|
-
|
|
336
|
-
-
|
|
337
|
-
instead of padding
|
|
338
|
-
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
[40-70 refreshes per day](https://sosumi.ai/documentation/widgetkit/keeping-a-widget-up-to-date)
|
|
343
|
-
with entries at least 5 minutes apart. Use `Text(timerInterval:countsDown:)`
|
|
344
|
-
for live countdowns instead of burning timeline entries.
|
|
345
|
-
|
|
346
|
-
See [references/widgetkit-advanced.md](references/widgetkit-advanced.md) for
|
|
347
|
-
code examples and detailed guidance on each pattern.
|
|
293
|
+
- Reach for `Gauge` before drawing arcs by hand. `.gaugeStyle(.accessoryCircular)`
|
|
294
|
+
suits circular Lock Screen widgets and `.linearCapacity` suits Home Screen
|
|
295
|
+
capacity bars; the system then handles styling, accessibility and rendering modes.
|
|
296
|
+
- From iOS 17, give the widget its background through
|
|
297
|
+
`.containerBackground(_:for: .widget)` instead of padding plus `.background`.
|
|
298
|
+
- Draw dense visuals such as sparklines or tiny bar charts with `Canvas`. Losing
|
|
299
|
+
per-element accessibility is acceptable because the whole widget is one tap target.
|
|
300
|
+
- Budget: roughly 40 to 70 refreshes a day, with entries 5 minutes apart or more.
|
|
301
|
+
For countdowns use `Text(timerInterval:countsDown:)` instead of one entry per tick.
|
|
348
302
|
|
|
349
303
|
## iOS 26 Additions
|
|
350
304
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
| `.desaturated` | Fully desaturated |
|
|
360
|
-
| `.fullColor` | Full-color rendering |
|
|
361
|
-
|
|
362
|
-
### WidgetPushHandler
|
|
363
|
-
|
|
364
|
-
Enable push-based timeline reloads without scheduled polling: implement
|
|
365
|
-
`WidgetPushHandler.pushTokenDidChange(_:widgets:)`, register the token with your
|
|
366
|
-
server, and send an APNs push to trigger a reload. See
|
|
367
|
-
[references/widgetkit-advanced.md](references/widgetkit-advanced.md) ("Push-Based Timeline Reloads") for
|
|
368
|
-
the handler plus the `ControlPushHandler` equivalent.
|
|
369
|
-
|
|
370
|
-
### CarPlay Widgets
|
|
371
|
-
|
|
372
|
-
`.systemSmall` widgets render in CarPlay on iOS 26+. Ensure small widget layouts
|
|
373
|
-
are legible at a glance for driver safety.
|
|
305
|
+
- `WidgetAccentedRenderingMode` (`.accented`, `.accentedDesaturated`,
|
|
306
|
+
`.desaturated`, `.fullColor`) controls how images adapt to Liquid Glass tinting.
|
|
307
|
+
- `WidgetPushHandler.pushTokenDidChange(_:widgets:)` gives you a token to send to
|
|
308
|
+
your server; an APNs push to it reloads the widget. `ControlPushHandler` does
|
|
309
|
+
the same for controls. See
|
|
310
|
+
[Reloading timelines by push](references/widgetkit-advanced.md#reloading-timelines-by-push-ios-26-and-later).
|
|
311
|
+
- `.systemSmall` widgets render in CarPlay from iOS 26. Keep them readable at a
|
|
312
|
+
glance so a driver is never pulled into detail.
|
|
374
313
|
|
|
375
314
|
## Common Mistakes
|
|
376
315
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
7. **Not handling the stale state.** Check `context.isStale` in Live Activity
|
|
401
|
-
views and show a fallback (e.g., "Updating...") when content is outdated.
|
|
402
|
-
|
|
403
|
-
8. **Putting heavy logic in the widget view.** Widget views are rendered in a
|
|
404
|
-
size-limited process. Pre-compute data in the timeline provider and pass
|
|
405
|
-
display-ready values through the entry.
|
|
406
|
-
|
|
407
|
-
9. **Ignoring accessory rendering modes.** Lock Screen widgets render in
|
|
408
|
-
`.vibrant` or `.accented` mode, not `.fullColor`. Test with
|
|
409
|
-
`@Environment(\.widgetRenderingMode)` and avoid relying on color alone.
|
|
410
|
-
|
|
411
|
-
10. **Not testing on device.** Dynamic Island and StandBy behavior differ
|
|
412
|
-
significantly from Simulator. Always verify on physical hardware.
|
|
316
|
+
- **Old provider.** `IntentTimelineProvider` belongs to the SiriKit Intents era;
|
|
317
|
+
write `AppIntentTimelineProvider`.
|
|
318
|
+
- **Burning the budget.** Calling `WidgetCenter.shared.reloadTimelines(ofKind:)`
|
|
319
|
+
after every small change drains refreshes. Batch changes and pick the right
|
|
320
|
+
`TimelineReloadPolicy`.
|
|
321
|
+
- **No App Group.** The extension runs in its own process. Share data through
|
|
322
|
+
`UserDefaults(suiteName:)` or the shared container.
|
|
323
|
+
- **Networking in `placeholder()`.** It must return sample data synchronously;
|
|
324
|
+
fetch in `getTimeline` or `timeline(for:in:)`.
|
|
325
|
+
- **Missing plist key.** If the main app's Info.plist lacks
|
|
326
|
+
`NSSupportsLiveActivities = YES`, no Live Activity will start.
|
|
327
|
+
- **Deprecated state APIs.** The request, update and end calls that take a bare
|
|
328
|
+
`contentState` are deprecated; pass `ActivityContent`.
|
|
329
|
+
- **Ignoring staleness.** Read `context.isStale` in the Live Activity view and
|
|
330
|
+
show something like "Updating..." when it is true.
|
|
331
|
+
- **Work in the view.** Widget views render in a memory-capped process. Compute
|
|
332
|
+
in the provider and pass ready-to-show values.
|
|
333
|
+
- **Assuming full color on the Lock Screen.** Lock Screen widgets draw in
|
|
334
|
+
`.vibrant` or `.accented`, not `.fullColor`. Check
|
|
335
|
+
`@Environment(\.widgetRenderingMode)` and never carry meaning by color alone.
|
|
336
|
+
- **Trusting the Simulator.** Dynamic Island and StandBy behave differently on
|
|
337
|
+
real devices; test there.
|
|
413
338
|
|
|
414
339
|
## Review Checklist
|
|
415
340
|
|
|
416
|
-
- [ ]
|
|
417
|
-
- [ ] `@main`
|
|
418
|
-
- [ ] `placeholder(in:)`
|
|
419
|
-
- [ ]
|
|
420
|
-
- [ ] Layout adapts per
|
|
421
|
-
- [ ] Interactive
|
|
422
|
-
- [ ] Live Activity:
|
|
423
|
-
- [ ] `
|
|
424
|
-
- [ ]
|
|
341
|
+
- [ ] App and extension share the same App Groups entitlement
|
|
342
|
+
- [ ] `@main` sits on the `WidgetBundle`, not on a single widget
|
|
343
|
+
- [ ] `placeholder(in:)` is synchronous; the snapshot is quick when `isPreview`
|
|
344
|
+
- [ ] Reload policy fits how often data changes; `reloadTimelines(ofKind:)` fires only on real changes
|
|
345
|
+
- [ ] Layout adapts per family; accessory widgets checked in `.vibrant`
|
|
346
|
+
- [ ] Interactive elements are `Button` or `Toggle` driven by an `AppIntent`
|
|
347
|
+
- [ ] Live Activity: Info.plist key present, `ActivityContent` used, all Dynamic Island closures written, `activity.end(_:dismissalPolicy:)` reached
|
|
348
|
+
- [ ] Controls use `StaticControlConfiguration` or `AppIntentControlConfiguration`
|
|
349
|
+
- [ ] Entry and intent types conform to `Sendable`
|
|
350
|
+
- [ ] Verified on a physical device
|
|
425
351
|
|
|
426
352
|
## References
|
|
427
353
|
|
|
428
|
-
-
|
|
429
|
-
-
|
|
354
|
+
- Longer patterns: [advanced reference](references/widgetkit-advanced.md)
|
|
355
|
+
- [WidgetKit](https://developer.apple.com/documentation/widgetkit)
|
|
356
|
+
- [ActivityKit](https://developer.apple.com/documentation/activitykit)
|
|
357
|
+
- [Keeping a widget up to date](https://developer.apple.com/documentation/widgetkit/keeping-a-widget-up-to-date)
|