@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,500 +1,492 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: alarmkit
|
|
3
|
-
description: "
|
|
3
|
+
description: "AlarmKit alarms and countdown timers on iOS and iPadOS 26: AlarmManager scheduling and authorization, AlarmAttributes, AlarmPresentation, AlarmButton stop and snooze, state observation, and the widget extension for countdown Live Activity UI on the Lock Screen, Dynamic Island, StandBy and paired Apple Watch. Use when an app needs wake-up alarms, countdown timers or any alert that needs the system alarm experience. Not for plain widgets or non-alarm Live Activities."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
|
-
# AlarmKit
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
Dynamic Island, StandBy, and a paired Apple Watch when the alarm fires. AlarmKit
|
|
11
|
-
requires iOS 26+ / iPadOS 26+. Alarms can break through Focus and Silent mode.
|
|
8
|
+
# AlarmKit
|
|
12
9
|
|
|
13
|
-
AlarmKit
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`AlarmPresentationState` used when scheduling.
|
|
10
|
+
AlarmKit lets an app hand an alarm or a countdown timer to the system. When it
|
|
11
|
+
fires, the alert shows up on the Lock Screen, in the Dynamic Island, in StandBy
|
|
12
|
+
and on the Apple Watch paired with the phone, and it can sound through Focus
|
|
13
|
+
and the Silent switch. The framework is available on iOS 26 and iPadOS 26 and later.
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
Under the hood an alarm is a Live Activity built on ActivityKit types, but the
|
|
16
|
+
firing alert itself is drawn by the system and cannot be restyled. The only
|
|
17
|
+
custom UI an app provides is for the countdown and paused states, and that UI
|
|
18
|
+
lives in a widget extension that uses the same `AlarmAttributes<Metadata>` and
|
|
19
|
+
`AlarmPresentationState` the app used when scheduling.
|
|
21
20
|
|
|
22
21
|
```swift
|
|
23
22
|
import AlarmKit
|
|
24
23
|
```
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- [Scheduling Alarms](#scheduling-alarms)
|
|
32
|
-
- [Countdown Timers](#countdown-timers)
|
|
33
|
-
- [Alarm States](#alarm-states)
|
|
34
|
-
- [AlarmAttributes and AlarmPresentation](#alarmattributes-and-alarmpresentation)
|
|
35
|
-
- [AlarmButton](#alarmbutton)
|
|
36
|
-
- [Live Activity Integration](#live-activity-integration)
|
|
37
|
-
- [Common Mistakes](#common-mistakes)
|
|
38
|
-
- [Review Checklist](#review-checklist)
|
|
39
|
-
- [References](#references)
|
|
25
|
+
Availability note: the `AlarmPresentation.Alert(title:secondaryButton:secondaryButtonBehavior:)`
|
|
26
|
+
initializer used throughout this skill is iOS 26.1+. On a 26.0 deployment target,
|
|
27
|
+
gate it with `if #available(iOS 26.1, *)`; the older initializer with a
|
|
28
|
+
`stopButton:` argument is deprecated from 26.1 and should only appear in that
|
|
29
|
+
fallback branch.
|
|
40
30
|
|
|
41
|
-
##
|
|
31
|
+
## Workflows
|
|
42
32
|
|
|
43
|
-
###
|
|
33
|
+
### Adding an alarm or timer
|
|
44
34
|
|
|
45
|
-
1.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
1. Put `NSAlarmKitUsageDescription` in the app's Info.plist with a sentence the
|
|
36
|
+
user will understand.
|
|
37
|
+
2. Ask for permission with `AlarmManager.shared.requestAuthorization()` at a
|
|
38
|
+
moment where the value is obvious, or let the system ask on the first
|
|
39
|
+
`schedule` call.
|
|
40
|
+
3. If the state comes back `.denied` (or anything other than `.authorized`),
|
|
41
|
+
show a recovery screen instead of scheduling.
|
|
42
|
+
4. Describe each state's text and buttons with `AlarmPresentation` (alert, plus
|
|
43
|
+
countdown and paused if used).
|
|
44
|
+
5. Wrap that in `AlarmAttributes` with optional metadata and a tint color.
|
|
45
|
+
6. Build an `AlarmManager.AlarmConfiguration`, either an alarm or a timer.
|
|
46
|
+
7. Call `AlarmManager.shared.schedule(id:configuration:)`.
|
|
47
|
+
8. Watch `alarmUpdates` to keep the UI in sync.
|
|
48
|
+
9. If a countdown is shown, create a widget extension; its
|
|
49
|
+
`ActivityConfiguration` must name the identical `AlarmAttributes<Metadata>` type.
|
|
54
50
|
|
|
55
|
-
###
|
|
51
|
+
### Reviewing existing alarm code
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
Go through the [Review checklist](#review-checklist) item by item.
|
|
58
54
|
|
|
59
55
|
## Authorization
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
is
|
|
64
|
-
and will not alert.
|
|
57
|
+
The user must grant access. The app may ask up front, or AlarmKit will prompt
|
|
58
|
+
the first time something is scheduled. If neither prompt ends in approval, no
|
|
59
|
+
alarm is scheduled and nothing will ring.
|
|
65
60
|
|
|
66
61
|
```swift
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
import AlarmKit
|
|
63
|
+
|
|
64
|
+
func ensureAlarmAccess() async -> Bool {
|
|
65
|
+
let center = AlarmManager.shared
|
|
66
|
+
switch center.authorizationState {
|
|
67
|
+
case .authorized:
|
|
68
|
+
return true
|
|
69
|
+
case .denied:
|
|
70
|
+
return false
|
|
71
|
+
case .notDetermined:
|
|
72
|
+
let answer = try? await center.requestAuthorization()
|
|
73
|
+
return answer == .authorized
|
|
74
|
+
@unknown default:
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func watchAlarmAccess(onChange: @escaping (Bool) -> Void) async {
|
|
80
|
+
for await state in AlarmManager.shared.authorizationUpdates {
|
|
81
|
+
switch state {
|
|
82
|
+
case .authorized: onChange(true)
|
|
83
|
+
case .denied, .notDetermined: onChange(false)
|
|
84
|
+
@unknown default: onChange(false)
|
|
85
|
+
}
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
`AlarmManager.AuthorizationState` has three cases: `.notDetermined`,
|
|
91
|
+
`.denied` and `.authorized`. `authorizationState` is a synchronous read;
|
|
92
|
+
`authorizationUpdates` is an async sequence of changes.
|
|
93
|
+
|
|
94
|
+
## Alarm or timer?
|
|
88
95
|
|
|
89
|
-
|
|
|
96
|
+
| | `.alarm` | `.timer` |
|
|
90
97
|
|---|---|---|
|
|
91
|
-
| Fires at
|
|
92
|
-
| Countdown UI |
|
|
93
|
-
|
|
|
94
|
-
|
|
|
98
|
+
| Fires | at a clock time | when a duration has elapsed |
|
|
99
|
+
| Countdown UI | optional | always shown |
|
|
100
|
+
| Repeats | yes, on chosen weekdays | no, one-shot |
|
|
101
|
+
| Typical use | wake-up, daily reminder | steeping tea, rest between sets |
|
|
95
102
|
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
Rule of thumb: the user picked a time of day, use `.alarm(schedule:...)`; the
|
|
104
|
+
user picked "in N minutes", use `.timer(duration:...)`.
|
|
98
105
|
|
|
99
|
-
## Scheduling
|
|
106
|
+
## Scheduling
|
|
100
107
|
|
|
101
108
|
### Alarm.Schedule
|
|
102
109
|
|
|
103
|
-
Alarms use `Alarm.Schedule` to define when they fire.
|
|
104
|
-
|
|
105
110
|
```swift
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
let
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// Recurring: fire at 6:00 AM on weekdays
|
|
116
|
-
let weekday: Alarm.Schedule = .relative(.init(
|
|
117
|
-
time: .init(hour: 6, minute: 0),
|
|
118
|
-
repeats: .weekly([.monday, .tuesday, .wednesday, .thursday, .friday])
|
|
119
|
-
))
|
|
111
|
+
import AlarmKit
|
|
112
|
+
|
|
113
|
+
let oneOff = Alarm.Schedule.fixed(Date(timeIntervalSinceNow: 3_600))
|
|
114
|
+
|
|
115
|
+
let sixAM = Alarm.Schedule.Relative.Time(hour: 6, minute: 0)
|
|
116
|
+
let tomorrowAtSix = Alarm.Schedule.relative(.init(time: sixAM, repeats: .never))
|
|
117
|
+
|
|
118
|
+
let classDays: [Locale.Weekday] = [.monday, .tuesday, .wednesday, .thursday, .friday]
|
|
119
|
+
let schoolRun = Alarm.Schedule.relative(.init(time: sixAM, repeats: .weekly(classDays)))
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
- `.fixed(Date)` rings once at that exact instant.
|
|
123
|
+
- `.relative` with `repeats: .never` rings once at a wall-clock time in the
|
|
124
|
+
device's current time zone.
|
|
125
|
+
- `.relative` with `repeats: .weekly([Locale.Weekday])` repeats on those days.
|
|
126
|
+
|
|
127
|
+
### Configuring and scheduling
|
|
123
128
|
|
|
124
129
|
```swift
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
time: .init(hour: 7, minute: 0),
|
|
132
|
-
repeats: .never
|
|
133
|
-
)),
|
|
134
|
-
attributes: attributes,
|
|
135
|
-
sound: .default
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
let alarm = try await AlarmManager.shared.schedule(
|
|
139
|
-
id: id,
|
|
140
|
-
configuration: configuration
|
|
141
|
-
)
|
|
142
|
-
```
|
|
130
|
+
import AlarmKit
|
|
131
|
+
import SwiftUI
|
|
132
|
+
|
|
133
|
+
struct ShiftInfo: AlarmMetadata {
|
|
134
|
+
var shiftName: String
|
|
135
|
+
}
|
|
143
136
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
137
|
+
@available(iOS 26.1, *)
|
|
138
|
+
func scheduleShiftAlarm() async throws -> Alarm {
|
|
139
|
+
let dawn = Alarm.Schedule.Relative.Time(hour: 5, minute: 30)
|
|
140
|
+
let alert = AlarmPresentation.Alert(
|
|
141
|
+
title: "Early shift",
|
|
142
|
+
secondaryButton: AlarmButton(text: "Later", textColor: .white, systemImageName: "zzz"),
|
|
143
|
+
secondaryButtonBehavior: .countdown
|
|
144
|
+
)
|
|
145
|
+
let attributes = AlarmAttributes(
|
|
146
|
+
presentation: AlarmPresentation(alert: alert),
|
|
147
|
+
metadata: ShiftInfo(shiftName: "Warehouse A"),
|
|
148
|
+
tintColor: .teal
|
|
149
|
+
)
|
|
150
|
+
let config = AlarmManager.AlarmConfiguration(
|
|
151
|
+
countdownDuration: Alarm.CountdownDuration(preAlert: nil, postAlert: 9 * 60),
|
|
152
|
+
schedule: .relative(.init(time: dawn, repeats: .never)),
|
|
153
|
+
attributes: attributes,
|
|
154
|
+
sound: .default
|
|
155
|
+
)
|
|
156
|
+
let center = AlarmManager.shared
|
|
157
|
+
return try await center.schedule(id: UUID(), configuration: config)
|
|
158
|
+
}
|
|
163
159
|
```
|
|
164
160
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
161
|
+
Here `postAlert` is what makes the secondary button a snooze: pressing it
|
|
162
|
+
starts a nine-minute countdown and then rings again.
|
|
163
|
+
|
|
164
|
+
`stopIntent` and `secondaryIntent` both default to `nil`, and that is usually
|
|
165
|
+
right:
|
|
166
|
+
|
|
167
|
+
- Leave `stopIntent` out when the system Stop is all you need. Pass one only
|
|
168
|
+
when stopping must also clean up app state or trigger some side effect.
|
|
169
|
+
- Leave `secondaryIntent` out for a plain snooze or repeat, which is
|
|
170
|
+
`secondaryButtonBehavior: .countdown` plus `CountdownDuration.postAlert`.
|
|
171
|
+
Pass one only with `.custom` behavior or when the app must do its own work.
|
|
172
|
+
|
|
173
|
+
### Lifecycle and transitions
|
|
174
|
+
|
|
175
|
+
The normal path is scheduled, then countdown, then alerting. From countdown
|
|
176
|
+
`pause(id:)` leads to paused and `resume(id:)` leads back. From alerting,
|
|
177
|
+
`stop(id:)` ends it and `countdown(id:)` snoozes it. `cancel(id:)` works from
|
|
178
|
+
anywhere.
|
|
179
|
+
|
|
180
|
+
| Call | Valid in | Effect |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| `cancel(id:)` | any state | deletes the alarm entirely, repeating ones included |
|
|
183
|
+
| `pause(id:)` | `.countdown` | freezes the countdown; throws elsewhere |
|
|
184
|
+
| `resume(id:)` | `.paused` | continues the countdown; throws elsewhere |
|
|
185
|
+
| `stop(id:)` | alerting | a one-shot alarm is deleted; a repeating one moves on to its next occurrence |
|
|
186
|
+
| `countdown(id:)` | `.alerting` | restarts the post-alert countdown (snooze); throws elsewhere |
|
|
170
187
|
|
|
171
|
-
## Countdown
|
|
188
|
+
## Countdown timers
|
|
172
189
|
|
|
173
|
-
|
|
174
|
-
`Alarm.CountdownDuration` to control pre-alert and post-alert durations.
|
|
190
|
+
A timer rings once a duration has passed and always shows its countdown.
|
|
175
191
|
|
|
176
192
|
```swift
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
)
|
|
193
|
+
import AlarmKit
|
|
194
|
+
import SwiftUI
|
|
195
|
+
|
|
196
|
+
struct BrewInfo: AlarmMetadata {
|
|
197
|
+
var blend: String
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@available(iOS 26.1, *)
|
|
201
|
+
func startSteepTimer() async throws {
|
|
202
|
+
let presentation = AlarmPresentation(
|
|
203
|
+
alert: .init(title: "Tea is ready"),
|
|
204
|
+
countdown: .init(title: "Steeping"),
|
|
205
|
+
paused: .init(title: "Steeping paused",
|
|
206
|
+
resumeButton: AlarmButton(text: "Resume", textColor: .white, systemImageName: "play.fill"))
|
|
207
|
+
)
|
|
208
|
+
let attributes = AlarmAttributes(presentation: presentation,
|
|
209
|
+
metadata: BrewInfo(blend: "Sencha"),
|
|
210
|
+
tintColor: .green)
|
|
211
|
+
let threeMinutes = AlarmManager.AlarmConfiguration.timer(duration: 180, attributes: attributes, sound: .default)
|
|
212
|
+
let center = AlarmManager.shared
|
|
213
|
+
_ = try await center.schedule(id: UUID(), configuration: threeMinutes)
|
|
214
|
+
}
|
|
189
215
|
```
|
|
190
216
|
|
|
191
217
|
### CountdownDuration
|
|
192
218
|
|
|
193
|
-
|
|
219
|
+
| Property | Meaning |
|
|
220
|
+
|---|---|
|
|
221
|
+
| `preAlert` | seconds counted down before the alert fires (the main countdown) |
|
|
222
|
+
| `postAlert` | seconds counted down after the alert when the user snoozes or repeats |
|
|
194
223
|
|
|
195
|
-
|
|
196
|
-
-
|
|
224
|
+
Both can be combined with a schedule. A 7:00 alarm with `preAlert: 900` shows a
|
|
225
|
+
fifteen-minute countdown starting at 6:45; `postAlert: 600` gives a ten-minute
|
|
226
|
+
snooze:
|
|
197
227
|
|
|
198
228
|
```swift
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
schedule: .relative(.init(
|
|
207
|
-
time: .init(hour: 8, minute: 0),
|
|
208
|
-
repeats: .never
|
|
209
|
-
)),
|
|
210
|
-
attributes: attributes,
|
|
211
|
-
sound: .default
|
|
212
|
-
)
|
|
229
|
+
import AlarmKit
|
|
230
|
+
|
|
231
|
+
func napDurations<M: AlarmMetadata>(_ attrs: AlarmAttributes<M>) -> AlarmManager.AlarmConfiguration<M> {
|
|
232
|
+
let seven = Alarm.Schedule.Relative.Time(hour: 7, minute: 0)
|
|
233
|
+
return .init(countdownDuration: .init(preAlert: 900, postAlert: 600),
|
|
234
|
+
schedule: .relative(.init(time: seven)), attributes: attrs, sound: .default)
|
|
235
|
+
}
|
|
213
236
|
```
|
|
214
237
|
|
|
215
|
-
## Alarm
|
|
238
|
+
## Alarm states
|
|
216
239
|
|
|
217
|
-
|
|
240
|
+
`Alarm.state` says where an alarm is in its lifecycle:
|
|
218
241
|
|
|
219
242
|
| State | Meaning |
|
|
220
243
|
|---|---|
|
|
221
|
-
| `.scheduled` |
|
|
222
|
-
| `.countdown` |
|
|
223
|
-
| `.paused` |
|
|
224
|
-
| `.alerting` |
|
|
244
|
+
| `.scheduled` | waiting for its time |
|
|
245
|
+
| `.countdown` | counting down (a timer, or an alarm's pre-alert) |
|
|
246
|
+
| `.paused` | countdown frozen by the user or the app |
|
|
247
|
+
| `.alerting` | ringing, with the prominent system UI |
|
|
225
248
|
|
|
226
|
-
### Observing
|
|
249
|
+
### Observing changes
|
|
227
250
|
|
|
228
|
-
`AlarmManager.shared.alarms`
|
|
229
|
-
|
|
230
|
-
|
|
251
|
+
Reading `AlarmManager.shared.alarms` can throw; it hands back whatever the
|
|
252
|
+
alarm daemon currently holds, so it needs `try` inside a throwing context or a `do/catch`.
|
|
253
|
+
Changes arrive through `alarmUpdates`:
|
|
231
254
|
|
|
232
255
|
```swift
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
let
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
for
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
case .paused: print("\(alarm.id) paused")
|
|
245
|
-
case .alerting: print("\(alarm.id) alerting!")
|
|
246
|
-
@unknown default: break
|
|
256
|
+
import AlarmKit
|
|
257
|
+
|
|
258
|
+
func trackAlarms(render: ([Alarm]) -> Void) async throws {
|
|
259
|
+
let center = AlarmManager.shared
|
|
260
|
+
render(try center.alarms)
|
|
261
|
+
for await batch in center.alarmUpdates {
|
|
262
|
+
for item in batch {
|
|
263
|
+
switch item.state {
|
|
264
|
+
case .scheduled, .countdown, .paused, .alerting: break
|
|
265
|
+
@unknown default: break
|
|
266
|
+
}
|
|
247
267
|
}
|
|
268
|
+
render(batch)
|
|
248
269
|
}
|
|
249
270
|
}
|
|
250
271
|
```
|
|
251
272
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
273
|
+
When an ID disappears from `alarmUpdates`, AlarmKit no longer has it scheduled.
|
|
274
|
+
The sequence does not say why. To tell a fired one-shot from a cancelled alarm
|
|
275
|
+
or a rescheduled one, compare against the IDs the app saved itself.
|
|
255
276
|
|
|
256
277
|
## AlarmAttributes and AlarmPresentation
|
|
257
278
|
|
|
258
|
-
`AlarmAttributes` conforms to `ActivityAttributes` and
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
to `nil`.
|
|
279
|
+
`AlarmAttributes` conforms to `ActivityAttributes` and carries the static part
|
|
280
|
+
of that Live Activity. Its generic parameter is `Metadata: AlarmMetadata`, a
|
|
281
|
+
protocol that refines `Decodable`, `Encodable`, `Hashable` and `Sendable`.
|
|
282
|
+
Passing `metadata` is optional; leave it out and it is `nil`.
|
|
263
283
|
|
|
264
284
|
### AlarmPresentation
|
|
265
285
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
286
|
+
`AlarmPresentation` describes the text and buttons per state. The system draws
|
|
287
|
+
the alerting UI from it; the widget extension may draw countdown and paused.
|
|
288
|
+
|
|
289
|
+
| Type | State | Required |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `AlarmPresentation.Alert(title:secondaryButton:secondaryButtonBehavior:)` | alerting | yes |
|
|
292
|
+
| `AlarmPresentation.Countdown(title:pauseButton:)` | counting down | no |
|
|
293
|
+
| `AlarmPresentation.Paused(title:resumeButton:)` | paused | no |
|
|
294
|
+
|
|
295
|
+
Combine them with `AlarmPresentation(alert:countdown:paused:)`:
|
|
269
296
|
|
|
270
297
|
```swift
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
)
|
|
279
|
-
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
let countdown = AlarmPresentation.Countdown(
|
|
284
|
-
title: "Morning Alarm",
|
|
285
|
-
pauseButton: AlarmButton(
|
|
286
|
-
text: "Pause",
|
|
287
|
-
textColor: .orange,
|
|
288
|
-
systemImageName: "pause.fill"
|
|
289
|
-
)
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
// Paused state (optional) -- shown when countdown is paused
|
|
293
|
-
let paused = AlarmPresentation.Paused(
|
|
294
|
-
title: "Paused",
|
|
295
|
-
resumeButton: AlarmButton(
|
|
296
|
-
text: "Resume",
|
|
297
|
-
textColor: .green,
|
|
298
|
-
systemImageName: "play.fill"
|
|
298
|
+
import AlarmKit
|
|
299
|
+
import SwiftUI
|
|
300
|
+
|
|
301
|
+
@available(iOS 26.1, *)
|
|
302
|
+
func workoutPresentation() -> AlarmPresentation {
|
|
303
|
+
let again = AlarmButton(text: "Again", textColor: .white, systemImageName: "repeat")
|
|
304
|
+
let hold = AlarmButton(text: "Hold", textColor: .orange, systemImageName: "pause.fill")
|
|
305
|
+
let go = AlarmButton(text: "Go", textColor: .orange, systemImageName: "play.fill")
|
|
306
|
+
return AlarmPresentation(
|
|
307
|
+
alert: .init(title: "Rest over", secondaryButton: again, secondaryButtonBehavior: .countdown),
|
|
308
|
+
countdown: .init(title: "Resting", pauseButton: hold),
|
|
309
|
+
paused: .init(title: "Rest on hold", resumeButton: go)
|
|
299
310
|
)
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
let presentation = AlarmPresentation(
|
|
303
|
-
alert: alert,
|
|
304
|
-
countdown: countdown,
|
|
305
|
-
paused: paused
|
|
306
|
-
)
|
|
311
|
+
}
|
|
307
312
|
```
|
|
308
313
|
|
|
309
|
-
###
|
|
314
|
+
### Metadata
|
|
310
315
|
|
|
311
316
|
```swift
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
var stepNumber: Int
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
let attributes = AlarmAttributes(
|
|
318
|
-
presentation: presentation,
|
|
319
|
-
metadata: CookingMetadata(recipeName: "Pasta", stepNumber: 3),
|
|
320
|
-
tintColor: .blue
|
|
321
|
-
)
|
|
317
|
+
import AlarmKit
|
|
318
|
+
import SwiftUI
|
|
322
319
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
metadata: nil,
|
|
326
|
-
tintColor: .blue
|
|
327
|
-
)
|
|
320
|
+
struct PlantInfo: AlarmMetadata { var plantName: String; var litres: Double }
|
|
321
|
+
struct NoAlarmData: AlarmMetadata {}
|
|
328
322
|
|
|
329
|
-
|
|
323
|
+
@available(iOS 26.1, *)
|
|
324
|
+
func plantAttributes() -> (AlarmAttributes<PlantInfo>, AlarmAttributes<NoAlarmData>) {
|
|
325
|
+
let look = AlarmPresentation(alert: .init(title: "Water the fern"))
|
|
326
|
+
let withData = AlarmAttributes(presentation: look, metadata: PlantInfo(plantName: "Fern", litres: 0.5), tintColor: .mint)
|
|
327
|
+
let plain = AlarmAttributes<NoAlarmData>(presentation: look, metadata: nil, tintColor: .mint)
|
|
328
|
+
return (withData, plain)
|
|
329
|
+
}
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
+
When there is nothing to carry, declare an empty type that conforms to
|
|
333
|
+
`AlarmMetadata` and pass `metadata: nil`.
|
|
334
|
+
|
|
332
335
|
### AlarmPresentationState
|
|
333
336
|
|
|
334
|
-
`AlarmPresentationState` is the
|
|
335
|
-
|
|
337
|
+
`AlarmPresentationState` is the alarm Live Activity's `ContentState`, owned and
|
|
338
|
+
updated by the system. It pairs an `alarmID` with a `mode` value:
|
|
336
339
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
+
| Mode | When | Carries |
|
|
341
|
+
|---|---|---|
|
|
342
|
+
| `.alert(Alert)` | ringing | the scheduled `time` |
|
|
343
|
+
| `.countdown(Countdown)` | counting down | fire date and durations |
|
|
344
|
+
| `.paused(Paused)` | paused | elapsed and total durations |
|
|
340
345
|
|
|
341
|
-
The widget extension
|
|
342
|
-
|
|
346
|
+
The widget extension switches on `context.state.mode` to choose Lock Screen and
|
|
347
|
+
Dynamic Island content for the non-alerting modes.
|
|
343
348
|
|
|
344
349
|
## AlarmButton
|
|
345
350
|
|
|
346
|
-
`AlarmButton`
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
text: "Stop",
|
|
351
|
-
textColor: .red,
|
|
352
|
-
systemImageName: "stop.fill"
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
let snoozeButton = AlarmButton(
|
|
356
|
-
text: "Snooze",
|
|
357
|
-
textColor: .white,
|
|
358
|
-
systemImageName: "bell.slash"
|
|
359
|
-
)
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Secondary Button Behavior
|
|
351
|
+
`AlarmButton(text:textColor:systemImageName:)` sets a button's label, color and
|
|
352
|
+
SF Symbol, for example a red `"stop.fill"` look for dismissing and a
|
|
353
|
+
`"bell.slash"` look for snoozing:
|
|
354
|
+
`AlarmButton(text: "Snooze", textColor: .yellow, systemImageName: "bell.slash")`.
|
|
363
355
|
|
|
364
|
-
|
|
356
|
+
### Secondary button behavior
|
|
365
357
|
|
|
366
|
-
| Behavior |
|
|
358
|
+
| Behavior | What happens |
|
|
367
359
|
|---|---|
|
|
368
|
-
| `.countdown` |
|
|
369
|
-
| `.custom` |
|
|
370
|
-
|
|
371
|
-
## Live Activity
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
whose `ActivityConfiguration`
|
|
377
|
-
used
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
`AlarmPresentation`, `AlarmPresentationState`, sound,
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
`com.apple.developer.alarmkit` unless a current Apple source documents them.
|
|
360
|
+
| `.countdown` | starts a new countdown of `postAlert` seconds (snooze) |
|
|
361
|
+
| `.custom` | runs `secondaryIntent`, for example to open the app |
|
|
362
|
+
|
|
363
|
+
## Live Activity integration
|
|
364
|
+
|
|
365
|
+
A ringing alarm is a Live Activity that the system renders on the Lock Screen,
|
|
366
|
+
in the Dynamic Island, in StandBy and on a paired Apple Watch; the app has no
|
|
367
|
+
say over that screen. Countdown and paused are different: the app supplies a widget
|
|
368
|
+
extension whose `ActivityConfiguration` names the same
|
|
369
|
+
`AlarmAttributes<Metadata>` type used at scheduling.
|
|
370
|
+
|
|
371
|
+
- Plan on the extension whenever countdown presentation is used. The metadata
|
|
372
|
+
type must be compiled into both the app and the extension, and it should stay
|
|
373
|
+
small.
|
|
374
|
+
- Leave the extension out and an alarm can vanish early or never ring. The
|
|
375
|
+
system only draws a fallback countdown in narrow cases, such as after a
|
|
376
|
+
restart before the first unlock.
|
|
377
|
+
|
|
378
|
+
AlarmKit is responsible for: permission to schedule alarms, `AlarmManager` scheduling and state,
|
|
379
|
+
`AlarmAttributes`, `AlarmPresentation`, `AlarmPresentationState`, the sound,
|
|
380
|
+
and the system Stop, Repeat and Open App actions. It is not a general surface
|
|
381
|
+
for custom notification UI.
|
|
382
|
+
|
|
383
|
+
When describing where alarms appear, name Lock Screen, Dynamic Island, StandBy
|
|
384
|
+
and paired Apple Watch together. Smart Stack is not an AlarmKit surface.
|
|
385
|
+
|
|
386
|
+
Hand-offs:
|
|
387
|
+
|
|
388
|
+
- Widgets on the Home Screen or in Smart Stack, `WidgetFamily`, timelines,
|
|
389
|
+
`WidgetCenter` reloads: `widgetkit`.
|
|
390
|
+
- Non-alarm Live Activities (`Activity.request`, `update`, `end`),
|
|
391
|
+
push-to-start and per-activity update tokens, and remote `content-state`
|
|
392
|
+
payloads: `activitykit`.
|
|
393
|
+
- APNs, `UNUserNotificationCenter`, notification categories and actions,
|
|
394
|
+
custom notification UI: `push-notifications`, unless the code ends up
|
|
395
|
+
calling `AlarmManager`.
|
|
396
|
+
|
|
397
|
+
Setup stays with what Apple documents: `NSAlarmKitUsageDescription` and
|
|
398
|
+
`AlarmManager` authorization. Do not require extra keys or a
|
|
399
|
+
`com.apple.developer.alarmkit` entitlement unless a current Apple source says so.
|
|
409
400
|
|
|
410
401
|
```swift
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
402
|
+
import ActivityKit
|
|
403
|
+
import AlarmKit
|
|
404
|
+
import SwiftUI
|
|
405
|
+
import WidgetKit
|
|
406
|
+
|
|
407
|
+
struct CoachInfo: AlarmMetadata {
|
|
408
|
+
var drill: String
|
|
415
409
|
}
|
|
416
410
|
|
|
417
|
-
struct
|
|
411
|
+
struct CoachAlarmWidget: Widget {
|
|
418
412
|
var body: some WidgetConfiguration {
|
|
419
|
-
ActivityConfiguration(for: AlarmAttributes<
|
|
420
|
-
|
|
421
|
-
|
|
413
|
+
ActivityConfiguration(for: AlarmAttributes<CoachInfo>.self) { context in
|
|
414
|
+
Text(context.attributes.metadata?.drill ?? "Timer")
|
|
415
|
+
.padding()
|
|
422
416
|
} dynamicIsland: { context in
|
|
423
417
|
DynamicIsland {
|
|
424
418
|
DynamicIslandExpandedRegion(.center) {
|
|
425
|
-
|
|
419
|
+
let heading = context.attributes.presentation.alert.title
|
|
420
|
+
Text(heading)
|
|
426
421
|
}
|
|
427
422
|
DynamicIslandExpandedRegion(.bottom) {
|
|
428
|
-
|
|
429
|
-
|
|
423
|
+
if case .countdown(let run) = context.state.mode {
|
|
424
|
+
Text(timerInterval: Date.now...run.fireDate, countsDown: true)
|
|
425
|
+
}
|
|
430
426
|
}
|
|
431
427
|
} compactLeading: {
|
|
432
428
|
Image(systemName: "alarm.fill")
|
|
433
429
|
} compactTrailing: {
|
|
434
|
-
|
|
430
|
+
Image(systemName: "alarm.fill")
|
|
435
431
|
} minimal: {
|
|
436
432
|
Image(systemName: "alarm.fill")
|
|
437
433
|
}
|
|
438
434
|
}
|
|
439
435
|
}
|
|
440
436
|
}
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
## Common Mistakes
|
|
444
|
-
|
|
445
|
-
**DON'T:** Forget `NSAlarmKitUsageDescription` in Info.plist.
|
|
446
|
-
**DO:** Add a descriptive usage string. Without it, AlarmKit cannot schedule alarms at all.
|
|
447
|
-
|
|
448
|
-
**DON'T:** Skip authorization and assume alarms will schedule.
|
|
449
|
-
**DO:** Call `requestAuthorization()` early and handle `.denied` gracefully.
|
|
450
|
-
|
|
451
|
-
**DON'T:** Use `.timer` when you need a recurring schedule.
|
|
452
|
-
**DO:** Use `.alarm` with `.weekly([...])` for recurring alarms. Timers are one-shot.
|
|
453
437
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
**DON'T:** Treat `stopIntent` and `secondaryIntent` as mandatory for every alarm.
|
|
463
|
-
**DO:** Omit them for standard system Stop/Snooze; provide intents only for app cleanup or custom behavior.
|
|
464
|
-
|
|
465
|
-
**DON'T:** Fold ordinary widgets, generic Live Activities, or push/local notification behavior into AlarmKit.
|
|
466
|
-
**DO:** Route Home Screen/Smart Stack widgets, `WidgetFamily`, timelines, and `WidgetCenter` reloads to `widgetkit`; route non-alarm `Activity.request`/`update`/`end`, push-to-start, update tokens, and remote `content-state` payloads to `activitykit`; route generic APNs, `UNUserNotificationCenter`, and notification categories/actions to `push-notifications` unless app code ultimately calls `AlarmManager`.
|
|
467
|
-
|
|
468
|
-
**DON'T:** Store large data in `AlarmMetadata`.
|
|
469
|
-
**DO:** Keep metadata lightweight or pass `nil`. Store large data in your app and reference by ID.
|
|
470
|
-
|
|
471
|
-
**DON'T:** Use deprecated `stopButton` parameter on `AlarmPresentation.Alert`.
|
|
472
|
-
**DO:** Use the current `init(title:secondaryButton:secondaryButtonBehavior:)` initializer.
|
|
473
|
-
|
|
474
|
-
## Review Checklist
|
|
438
|
+
@main
|
|
439
|
+
struct CoachWidgets: WidgetBundle {
|
|
440
|
+
var body: some Widget {
|
|
441
|
+
CoachAlarmWidget()
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
```
|
|
475
445
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
-
|
|
479
|
-
-
|
|
480
|
-
|
|
481
|
-
-
|
|
482
|
-
|
|
483
|
-
-
|
|
484
|
-
|
|
485
|
-
-
|
|
486
|
-
|
|
487
|
-
-
|
|
488
|
-
|
|
489
|
-
-
|
|
490
|
-
-
|
|
491
|
-
|
|
492
|
-
-
|
|
446
|
+
## Common mistakes
|
|
447
|
+
|
|
448
|
+
- **No `NSAlarmKitUsageDescription`.** Nothing can be scheduled.
|
|
449
|
+
- **Skipping authorization.** Ask early with `requestAuthorization()` and give
|
|
450
|
+
`.denied` a real screen.
|
|
451
|
+
- **Recurring timers.** Timers are one-shot. Use `.alarm` with
|
|
452
|
+
`.weekly([...])` for repetition.
|
|
453
|
+
- **Countdown without the widget extension.** Alarms can be dismissed before
|
|
454
|
+
they ring; the fallback UI covers very little.
|
|
455
|
+
- **Hand-tracking state.** Alarms change state while the app is suspended.
|
|
456
|
+
Read it from `alarmUpdates`.
|
|
457
|
+
- **Treating `stopIntent` or `secondaryIntent` as required.** Leave both out
|
|
458
|
+
for the standard Stop and Snooze.
|
|
459
|
+
- **Pulling other features into AlarmKit.** Route them as listed under Hand-offs.
|
|
460
|
+
- **Heavy metadata.** Keep `AlarmMetadata` small or `nil`; keep large data in
|
|
461
|
+
the app and refer to it by ID.
|
|
462
|
+
- **The deprecated `stopButton` argument.** Use
|
|
463
|
+
`AlarmPresentation.Alert(title:secondaryButton:secondaryButtonBehavior:)`
|
|
464
|
+
(iOS 26.1+); keep the `stopButton:` form only in a 26.0 fallback branch.
|
|
465
|
+
|
|
466
|
+
## Review checklist
|
|
467
|
+
|
|
468
|
+
- [ ] `NSAlarmKitUsageDescription` is present and not empty
|
|
469
|
+
- [ ] Authorization is requested and `.denied` has UI
|
|
470
|
+
- [ ] `AlarmPresentation` covers every state the app uses (alert, countdown, paused)
|
|
471
|
+
- [ ] Any countdown has a matching widget extension whose `ActivityConfiguration` names the same `AlarmAttributes<Metadata>`
|
|
472
|
+
- [ ] Metadata conforms to `AlarmMetadata`, stays small, and is `nil` if there is none
|
|
473
|
+
- [ ] Each alarm ID is saved for later cancel, pause, resume or stop
|
|
474
|
+
- [ ] `alarmUpdates` is observed
|
|
475
|
+
- [ ] `stopIntent` and `secondaryIntent` are omitted for standard behavior and only passed for cleanup or custom work
|
|
476
|
+
- [ ] `postAlert` is set when `.countdown` snooze is used
|
|
477
|
+
- [ ] AlarmKit is credited only with authorization, `AlarmManager` scheduling and state, attributes, presentation, presentation state, sound and system alarm actions
|
|
478
|
+
- [ ] The ringing screen is described as drawn by the system
|
|
479
|
+
- [ ] Custom countdown and paused UI lives in the widget extension with the same attributes and `AlarmPresentationState`
|
|
480
|
+
- [ ] Hand-offs to `widgetkit`, `activitykit` and `push-notifications` are explicit
|
|
481
|
+
- [ ] Setup cites only documented requirements; no `com.apple.developer.alarmkit` unless Apple documents it
|
|
482
|
+
- [ ] `tintColor` is set on `AlarmAttributes` so the alarm is recognisable
|
|
483
|
+
- [ ] `AlarmManager.AlarmError.maximumLimitReached` is handled
|
|
484
|
+
- [ ] Sound and vibration are tested on a device, not only in Simulator
|
|
493
485
|
|
|
494
486
|
## References
|
|
495
487
|
|
|
496
|
-
-
|
|
497
|
-
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
488
|
+
- [AlarmKit patterns](references/alarmkit-patterns.md) - complete alarm and timer flows, authorization manager, state store, widget extension, recurrence, snooze and custom actions, Info.plist, errors
|
|
489
|
+
- [AlarmKit](https://developer.apple.com/documentation/alarmkit)
|
|
490
|
+
- [AlarmManager](https://developer.apple.com/documentation/alarmkit/alarmmanager)
|
|
491
|
+
- [AlarmAttributes](https://developer.apple.com/documentation/alarmkit/alarmattributes)
|
|
492
|
+
- [Apple sample: scheduling alarms](https://developer.apple.com/documentation/alarmkit/scheduling-an-alarm-with-alarmkit)
|