@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1
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 +21 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +285 -285
- package/package.json +3 -3
- package/pipeline/lib/redact.mjs +3 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/scripts/gen-skills-index.mjs +13 -1
- package/pipeline/scripts/pre-commit-check.sh +4 -0
- package/pipeline/skills/.skill-manifest.json +69 -69
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +345 -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 +107 -121
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +145 -165
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +306 -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 +335 -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 +277 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +135 -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 +274 -384
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +173 -321
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +228 -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 +302 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +236 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
- package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +1 -1
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +8 -7
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +5 -2
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +100 -0
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +45 -26
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +14 -16
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +12 -5
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +2 -1
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +6 -5
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +44 -18
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +5 -2
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +10 -11
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +4 -33
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +12 -59
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +297 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/skill-creator/template.md +7 -1
- 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 +302 -241
- 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 +304 -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 +183 -162
- 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 +411 -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 +375 -491
- 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 +397 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +191 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +81 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +394 -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 +201 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +134 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +111 -138
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +160 -315
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +224 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +416 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,412 +1,257 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: weatherkit
|
|
3
|
-
description: "
|
|
3
|
+
description: "WeatherKit on iOS: current, hourly, daily and minute forecasts, alerts, historical statistics, dataset selection, caching. Use when integrating weather data, showing forecasts, handling severe alerts or displaying the required Apple Weather attribution and legal link."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# WeatherKit
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
attribution
|
|
10
|
+
WeatherKit gives an app the same forecast data the system Weather app uses,
|
|
11
|
+
through one async service. The rules that matter most are legal and economic:
|
|
12
|
+
attribution is required wherever the data shows, and every dataset you request
|
|
13
|
+
counts against the app's quota. Code targets Swift 6.3 and iOS 26.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
- [Fetching Current Weather](#fetching-current-weather)
|
|
18
|
-
- [Forecasts](#forecasts)
|
|
19
|
-
- [Weather Alerts](#weather-alerts)
|
|
20
|
-
- [Selective Queries](#selective-queries)
|
|
21
|
-
- [Attribution](#attribution)
|
|
22
|
-
- [Availability](#availability)
|
|
23
|
-
- [Common Mistakes](#common-mistakes)
|
|
24
|
-
- [Review Checklist](#review-checklist)
|
|
25
|
-
- [References](#references)
|
|
15
|
+
Dashboard, charts, historical statistics, condition mapping, caching and
|
|
16
|
+
location plumbing are in
|
|
17
|
+
[references/weatherkit-patterns.md](references/weatherkit-patterns.md).
|
|
26
18
|
|
|
27
19
|
## Setup
|
|
28
20
|
|
|
29
|
-
### Project
|
|
21
|
+
### Project configuration
|
|
30
22
|
|
|
31
|
-
1.
|
|
32
|
-
2.
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
1. In Xcode, add the **WeatherKit** capability. This writes the entitlement.
|
|
24
|
+
2. In the developer portal, enable WeatherKit for the same App ID (both the
|
|
25
|
+
capability and the service checkbox are needed).
|
|
26
|
+
3. The account must be a paid, currently active developer program membership.
|
|
27
|
+
4. If the app sends the device's own position, add
|
|
28
|
+
`NSLocationWhenInUseUsageDescription` and get location permission first.
|
|
35
29
|
|
|
36
|
-
###
|
|
30
|
+
### Imports and the service
|
|
37
31
|
|
|
38
32
|
```swift
|
|
39
33
|
import WeatherKit
|
|
40
34
|
import CoreLocation
|
|
35
|
+
|
|
36
|
+
let forecaster = WeatherService.shared // or WeatherService()
|
|
41
37
|
```
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
`WeatherService` is `Sendable`, so one instance can be used from any task or
|
|
40
|
+
actor.
|
|
41
|
+
|
|
42
|
+
## Fetching current weather
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
thread-safe.
|
|
44
|
+
The plain call returns every dataset in a `Weather` value:
|
|
47
45
|
|
|
48
46
|
```swift
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
let
|
|
47
|
+
let site = CLLocation(latitude: 38.42, longitude: 27.14)
|
|
48
|
+
let report = try await forecaster.weather(for: site)
|
|
49
|
+
let now = report.currentWeather
|
|
52
50
|
```
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
`CurrentWeather` fields you will use most:
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
| Property | Type | Note |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `temperature` | `Measurement<UnitTemperature>` | Format with `.formatted()` |
|
|
57
|
+
| `condition` | `WeatherCondition` | Enum with a readable `description` |
|
|
58
|
+
| `symbolName` | `String` | An SF Symbol name |
|
|
59
|
+
| `humidity` | `Double` | Fraction from 0 to 1 |
|
|
60
|
+
| `wind` | `Wind` | `speed`, `direction`, `gust` |
|
|
61
|
+
| `uvIndex` | `UVIndex` | `value` and `category` |
|
|
58
62
|
|
|
59
63
|
```swift
|
|
60
|
-
|
|
61
|
-
let weather = try await weatherService.weather(for: location)
|
|
62
|
-
return weather.currentWeather
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Using the result
|
|
66
|
-
func displayCurrent(_ current: CurrentWeather) {
|
|
67
|
-
let temp = current.temperature // Measurement<UnitTemperature>
|
|
68
|
-
let condition = current.condition // WeatherCondition enum
|
|
69
|
-
let symbol = current.symbolName // SF Symbol name
|
|
70
|
-
let humidity = current.humidity // Double (0-1)
|
|
71
|
-
let wind = current.wind // Wind (speed, direction, gust)
|
|
72
|
-
let uvIndex = current.uvIndex // UVIndex
|
|
73
|
-
|
|
74
|
-
print("\(condition): \(temp.formatted())")
|
|
75
|
-
}
|
|
64
|
+
headline = "\(now.temperature.formatted()), \(now.condition.description)"
|
|
76
65
|
```
|
|
77
66
|
|
|
78
67
|
## Forecasts
|
|
79
68
|
|
|
80
|
-
### Hourly
|
|
69
|
+
### Hourly
|
|
81
70
|
|
|
82
|
-
|
|
71
|
+
At the time of writing, Apple's documentation says the default hourly forecast
|
|
72
|
+
covers 25 consecutive hours starting with the current hour; read the count from
|
|
73
|
+
the result rather than hard-coding it. `hourlyForecast` is a `Forecast<HourWeather>`:
|
|
83
74
|
|
|
84
75
|
```swift
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return weather.hourlyForecast
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Iterate hours
|
|
91
|
-
for hour in hourlyForecast {
|
|
92
|
-
print("\(hour.date): \(hour.temperature.formatted()), \(hour.condition)")
|
|
76
|
+
let timeline = report.hourlyForecast.map { slot in
|
|
77
|
+
(slot.date.formatted(.dateTime.hour()), slot.temperature.formatted(), slot.condition.description)
|
|
93
78
|
}
|
|
94
79
|
```
|
|
95
80
|
|
|
96
|
-
### Daily
|
|
81
|
+
### Daily
|
|
97
82
|
|
|
98
|
-
|
|
83
|
+
At the time of writing, Apple's documentation says the default daily forecast
|
|
84
|
+
covers 10 consecutive days starting today; again, read the count from the
|
|
85
|
+
result.
|
|
86
|
+
`dailyForecast` is a `Forecast<DayWeather>`:
|
|
99
87
|
|
|
100
88
|
```swift
|
|
101
|
-
|
|
102
|
-
let
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Iterate days
|
|
107
|
-
for day in dailyForecast {
|
|
108
|
-
print("\(day.date): \(day.lowTemperature.formatted()) - \(day.highTemperature.formatted())")
|
|
109
|
-
print(" Condition: \(day.condition), Precipitation: \(day.precipitationChance)")
|
|
89
|
+
for day in report.dailyForecast {
|
|
90
|
+
let range = "\(day.lowTemperature.formatted()) to \(day.highTemperature.formatted())"
|
|
91
|
+
let rain = day.precipitationChance.formatted(.percent)
|
|
92
|
+
rows.append("\(day.condition.description), \(range), rain \(rain)")
|
|
110
93
|
}
|
|
111
94
|
```
|
|
112
95
|
|
|
113
|
-
###
|
|
114
|
-
|
|
115
|
-
Request forecasts for specific date ranges using `WeatherQuery`.
|
|
96
|
+
### A custom range
|
|
116
97
|
|
|
117
98
|
```swift
|
|
118
|
-
func
|
|
119
|
-
let
|
|
120
|
-
let
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
for:
|
|
124
|
-
including: .daily(startDate:
|
|
99
|
+
func nextWeek(at site: CLLocation) async throws -> Forecast<DayWeather>? {
|
|
100
|
+
let weekStart = Date.now
|
|
101
|
+
guard let weekEnd = Calendar.current.date(byAdding: DateComponents(day: 7), to: weekStart) else { return nil }
|
|
102
|
+
let service = WeatherService.shared
|
|
103
|
+
return try await service.weather(
|
|
104
|
+
for: site,
|
|
105
|
+
including: .daily(startDate: weekStart, endDate: weekEnd)
|
|
125
106
|
)
|
|
126
|
-
return forecast
|
|
127
107
|
}
|
|
128
108
|
```
|
|
129
109
|
|
|
130
|
-
|
|
110
|
+
`.hourly(startDate:endDate:)` works the same way for hours.
|
|
131
111
|
|
|
132
|
-
|
|
133
|
-
and affected regions.
|
|
112
|
+
## Weather alerts
|
|
134
113
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
let weather = try await weatherService.weather(for: location)
|
|
138
|
-
return weather.weatherAlerts
|
|
139
|
-
}
|
|
114
|
+
`weatherAlerts` is `[WeatherAlert]?`; it is `nil` where alerts are not
|
|
115
|
+
provided.
|
|
140
116
|
|
|
141
|
-
|
|
142
|
-
if let alerts = weatherAlerts {
|
|
117
|
+
```swift
|
|
118
|
+
if let alerts = report.weatherAlerts {
|
|
143
119
|
for alert in alerts {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if let detailsURL = alert.detailsURL {
|
|
148
|
-
// Link to full alert details
|
|
149
|
-
}
|
|
120
|
+
// alert.summary: String, alert.severity: WeatherSeverity,
|
|
121
|
+
// alert.region: String?, alert.detailsURL: URL, alert.source: String
|
|
122
|
+
banners.append(alert.summary)
|
|
150
123
|
}
|
|
151
124
|
}
|
|
152
125
|
```
|
|
153
126
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Fetch only the datasets you need to minimize API usage and response size. Each
|
|
157
|
-
`WeatherQuery` type maps to one dataset.
|
|
158
|
-
|
|
159
|
-
### Single Dataset
|
|
127
|
+
`detailsURL` is not optional; link to it so users can read the full notice
|
|
128
|
+
from the issuing agency.
|
|
160
129
|
|
|
161
|
-
|
|
162
|
-
let current = try await weatherService.weather(
|
|
163
|
-
for: location,
|
|
164
|
-
including: .current
|
|
165
|
-
)
|
|
166
|
-
// current is CurrentWeather
|
|
167
|
-
```
|
|
130
|
+
## Selective queries
|
|
168
131
|
|
|
169
|
-
|
|
132
|
+
Ask only for what the screen shows. Each `WeatherQuery` maps to one dataset,
|
|
133
|
+
and each dataset is a request against the quota and more bytes over the wire.
|
|
170
134
|
|
|
171
135
|
```swift
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
including: .current, .hourly, .daily
|
|
175
|
-
)
|
|
176
|
-
// current: CurrentWeather, hourly: Forecast<HourWeather>, daily: Forecast<DayWeather>
|
|
177
|
-
```
|
|
136
|
+
// One dataset: the return type is the dataset itself.
|
|
137
|
+
let nowOnly: CurrentWeather = try await forecaster.weather(for: site, including: .current)
|
|
178
138
|
|
|
179
|
-
|
|
139
|
+
// Several datasets: the results come back as a tuple, in the order requested.
|
|
140
|
+
let (now, hours, days) = try await forecaster.weather(for: site, including: .current, .hourly, .daily)
|
|
180
141
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
let minuteForecast = try await weatherService.weather(
|
|
186
|
-
for: location,
|
|
187
|
-
including: .minute
|
|
188
|
-
)
|
|
189
|
-
// minuteForecast: Forecast<MinuteWeather>? (nil if unavailable)
|
|
142
|
+
// Next-hour precipitation, minute by minute. Only some regions have it.
|
|
143
|
+
if let nextHour = try await forecaster.weather(for: site, including: .minute) {
|
|
144
|
+
rainStartsSoon = nextHour.contains { $0.precipitationChance > 0.5 }
|
|
145
|
+
}
|
|
190
146
|
```
|
|
191
147
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
196
|
-
| `.
|
|
197
|
-
| `.
|
|
198
|
-
| `.
|
|
199
|
-
| `.
|
|
200
|
-
| `.alerts` | `[WeatherAlert]?` | Active weather alerts |
|
|
201
|
-
| `.availability` | `WeatherAvailability` | Dataset availability for location |
|
|
148
|
+
| Query | Result type | Notes |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| `.current` | `CurrentWeather` | |
|
|
151
|
+
| `.hourly` | `Forecast<HourWeather>` | Default span per Apple's docs: 25 hours from now |
|
|
152
|
+
| `.daily` | `Forecast<DayWeather>` | Default span per Apple's docs: 10 days from today |
|
|
153
|
+
| `.minute` | `Forecast<MinuteWeather>?` | `nil` where unsupported |
|
|
154
|
+
| `.alerts` | `[WeatherAlert]?` | `nil` where unsupported |
|
|
155
|
+
| `.availability` | `WeatherAvailability` | Which region-limited datasets exist here |
|
|
202
156
|
|
|
203
157
|
## Attribution
|
|
204
158
|
|
|
205
|
-
Apple
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
### Fetching Attribution
|
|
159
|
+
Showing Apple Weather attribution is a legal requirement of using WeatherKit,
|
|
160
|
+
not a design choice. Fetch it from the service:
|
|
209
161
|
|
|
210
162
|
```swift
|
|
211
|
-
|
|
212
|
-
return try await weatherService.attribution
|
|
213
|
-
}
|
|
163
|
+
let credit = try await forecaster.attribution
|
|
214
164
|
```
|
|
215
165
|
|
|
216
|
-
|
|
166
|
+
Pick the mark that matches the color scheme and link to the legal page:
|
|
217
167
|
|
|
218
168
|
```swift
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
struct WeatherAttributionView: View {
|
|
223
|
-
let attribution: WeatherAttribution
|
|
224
|
-
@Environment(\.colorScheme) private var colorScheme
|
|
169
|
+
struct WeatherCredit: View {
|
|
170
|
+
let credit: WeatherAttribution
|
|
171
|
+
@Environment(\.colorScheme) private var scheme
|
|
225
172
|
|
|
226
173
|
var body: some View {
|
|
227
|
-
VStack {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
image
|
|
231
|
-
.resizable()
|
|
232
|
-
.scaledToFit()
|
|
233
|
-
.frame(height: 20)
|
|
174
|
+
VStack(spacing: 6) {
|
|
175
|
+
AsyncImage(url: scheme == .dark ? credit.combinedMarkDarkURL : credit.combinedMarkLightURL) { mark in
|
|
176
|
+
mark.resizable().scaledToFit()
|
|
234
177
|
} placeholder: {
|
|
235
|
-
|
|
178
|
+
Text(credit.serviceName).font(.caption2)
|
|
236
179
|
}
|
|
180
|
+
.frame(height: 14)
|
|
237
181
|
|
|
238
|
-
|
|
239
|
-
Link("Weather data sources", destination: attribution.legalPageURL)
|
|
182
|
+
Link("Other data sources", destination: credit.legalPageURL)
|
|
240
183
|
.font(.caption2)
|
|
241
|
-
.foregroundStyle(.secondary)
|
|
242
184
|
}
|
|
243
185
|
}
|
|
244
|
-
|
|
245
|
-
private var markURL: URL {
|
|
246
|
-
colorScheme == .dark
|
|
247
|
-
? attribution.combinedMarkDarkURL
|
|
248
|
-
: attribution.combinedMarkLightURL
|
|
249
|
-
}
|
|
250
186
|
}
|
|
251
187
|
```
|
|
252
188
|
|
|
253
|
-
|
|
189
|
+
`WeatherAttribution` provides:
|
|
254
190
|
|
|
255
191
|
| Property | Use |
|
|
256
|
-
|
|
257
|
-
| `combinedMarkLightURL` |
|
|
258
|
-
| `combinedMarkDarkURL` |
|
|
259
|
-
| `squareMarkURL` |
|
|
260
|
-
| `legalPageURL` |
|
|
261
|
-
| `legalAttributionText` |
|
|
262
|
-
| `serviceName` |
|
|
192
|
+
| --- | --- |
|
|
193
|
+
| `combinedMarkLightURL` | Mark for light backgrounds |
|
|
194
|
+
| `combinedMarkDarkURL` | Mark for dark backgrounds |
|
|
195
|
+
| `squareMarkURL` | Compact square mark |
|
|
196
|
+
| `legalPageURL` | Page listing data sources; link to it |
|
|
197
|
+
| `legalAttributionText` | Plain-text alternative when showing a web page is not practical |
|
|
198
|
+
| `serviceName` | The provider name, "Apple Weather" |
|
|
263
199
|
|
|
264
200
|
## Availability
|
|
265
201
|
|
|
266
|
-
|
|
267
|
-
|
|
202
|
+
Minute forecasts and alerts are not offered in every country. Ask before
|
|
203
|
+
building UI around them:
|
|
268
204
|
|
|
269
205
|
```swift
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
including: .availability
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
// Check specific dataset availability
|
|
277
|
-
if availability.alertAvailability == .available {
|
|
278
|
-
// Safe to fetch alerts
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if availability.minuteAvailability == .available {
|
|
282
|
-
// Minute forecast available for this region
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
## Common Mistakes
|
|
288
|
-
|
|
289
|
-
### DON'T: Ship without Apple Weather attribution
|
|
290
|
-
|
|
291
|
-
Omitting attribution violates the WeatherKit terms of service and risks App Review
|
|
292
|
-
rejection.
|
|
293
|
-
|
|
294
|
-
```swift
|
|
295
|
-
// WRONG: Show weather data without attribution
|
|
296
|
-
VStack {
|
|
297
|
-
Text("72F, Sunny")
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// CORRECT: Always include attribution
|
|
301
|
-
VStack {
|
|
302
|
-
Text("72F, Sunny")
|
|
303
|
-
WeatherAttributionView(attribution: attribution)
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### DON'T: Fetch all datasets when you only need current conditions
|
|
308
|
-
|
|
309
|
-
Each dataset query counts against your API quota. Fetch only what you display.
|
|
310
|
-
|
|
311
|
-
```swift
|
|
312
|
-
// WRONG: Fetches everything
|
|
313
|
-
let weather = try await weatherService.weather(for: location)
|
|
314
|
-
let temp = weather.currentWeather.temperature
|
|
315
|
-
|
|
316
|
-
// CORRECT: Fetch only current conditions
|
|
317
|
-
let current = try await weatherService.weather(
|
|
318
|
-
for: location,
|
|
319
|
-
including: .current
|
|
320
|
-
)
|
|
321
|
-
let temp = current.temperature
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
### DON'T: Ignore minute forecast unavailability
|
|
325
|
-
|
|
326
|
-
Minute forecasts return `nil` in unsupported regions. Force-unwrapping crashes.
|
|
327
|
-
|
|
328
|
-
```swift
|
|
329
|
-
// WRONG: Force-unwrap minute forecast
|
|
330
|
-
let minutes = try await weatherService.weather(for: location, including: .minute)
|
|
331
|
-
for m in minutes! { ... } // Crash in unsupported regions
|
|
332
|
-
|
|
333
|
-
// CORRECT: Handle nil
|
|
334
|
-
if let minutes = try await weatherService.weather(for: location, including: .minute) {
|
|
335
|
-
for m in minutes { ... }
|
|
336
|
-
} else {
|
|
337
|
-
// Minute forecast not available for this region
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### DON'T: Forget the WeatherKit entitlement
|
|
342
|
-
|
|
343
|
-
Without the capability enabled, `WeatherService` calls throw at runtime.
|
|
344
|
-
|
|
345
|
-
```swift
|
|
346
|
-
// WRONG: No WeatherKit capability configured
|
|
347
|
-
let weather = try await weatherService.weather(for: location) // Throws
|
|
348
|
-
|
|
349
|
-
// CORRECT: Enable WeatherKit in Xcode Signing & Capabilities
|
|
350
|
-
// and in the Apple Developer portal for your App ID
|
|
351
|
-
```
|
|
352
|
-
|
|
353
|
-
### DON'T: Make repeated requests without caching
|
|
354
|
-
|
|
355
|
-
Weather data updates every few minutes, not every second. Cache responses
|
|
356
|
-
to stay within API quotas and improve performance.
|
|
357
|
-
|
|
358
|
-
```swift
|
|
359
|
-
// WRONG: Fetch on every view appearance
|
|
360
|
-
.task {
|
|
361
|
-
let weather = try? await fetchWeather()
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// CORRECT: Cache with a staleness interval
|
|
365
|
-
actor WeatherCache {
|
|
366
|
-
private var cached: CurrentWeather?
|
|
367
|
-
private var lastFetch: Date?
|
|
368
|
-
|
|
369
|
-
func current(for location: CLLocation) async throws -> CurrentWeather {
|
|
370
|
-
if let cached, let lastFetch,
|
|
371
|
-
Date.now.timeIntervalSince(lastFetch) < 600 {
|
|
372
|
-
return cached
|
|
373
|
-
}
|
|
374
|
-
let fresh = try await WeatherService.shared.weather(
|
|
375
|
-
for: location, including: .current
|
|
376
|
-
)
|
|
377
|
-
cached = fresh
|
|
378
|
-
lastFetch = .now
|
|
379
|
-
return fresh
|
|
380
|
-
}
|
|
381
|
-
}
|
|
206
|
+
let coverage = try await forecaster.weather(for: site, including: .availability)
|
|
207
|
+
let offersAlerts = coverage.alertAvailability == .available
|
|
208
|
+
let offersNextHour = coverage.minuteAvailability == .available
|
|
382
209
|
```
|
|
383
210
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
211
|
+
Each is a `WeatherAvailability.AvailabilityKind`: `.available`,
|
|
212
|
+
`.temporarilyUnavailable`, `.unsupported` or `.unknown`.
|
|
213
|
+
|
|
214
|
+
## Common mistakes
|
|
215
|
+
|
|
216
|
+
1. **No attribution.** Leaving it out breaks the WeatherKit terms and is a
|
|
217
|
+
reason for App Review to reject the app.
|
|
218
|
+
2. **Fetching everything to show one number.** `weather(for:)` returns every
|
|
219
|
+
dataset and each one counts against the quota. Use
|
|
220
|
+
`weather(for:including: .current)` when only current conditions appear.
|
|
221
|
+
3. **Force-unwrapping the minute forecast.** It is `nil` in unsupported
|
|
222
|
+
regions and the app crashes there. Use `if let`.
|
|
223
|
+
4. **Missing capability.** Without the capability and the portal switch,
|
|
224
|
+
`WeatherService` calls throw at runtime.
|
|
225
|
+
5. **Refetching on every appearance.** Weather does not change second to
|
|
226
|
+
second. Cache results with a staleness window, for example an actor that
|
|
227
|
+
keeps entries for 600 seconds (see the reference file).
|
|
228
|
+
|
|
229
|
+
## Review checklist
|
|
230
|
+
|
|
231
|
+
- [ ] WeatherKit capability added in Xcode and enabled in the portal
|
|
232
|
+
- [ ] Active developer program membership
|
|
233
|
+
- [ ] Attribution visible wherever weather data appears
|
|
234
|
+
- [ ] Attribution mark follows light and dark mode
|
|
235
|
+
- [ ] Legal page linked, or `legalAttributionText` shown
|
|
236
|
+
- [ ] Only the datasets the screen needs are requested
|
|
237
|
+
- [ ] Minute forecast treated as optional
|
|
238
|
+
- [ ] Alerts nil-checked
|
|
239
|
+
- [ ] Responses cached for 5 to 15 minutes
|
|
240
|
+
- [ ] `WeatherAvailability` checked before region-limited datasets
|
|
241
|
+
- [ ] Location permission granted before a device `CLLocation` is passed in
|
|
242
|
+
- [ ] Measurements displayed with `formatted()` so units follow the locale
|
|
398
243
|
|
|
399
244
|
## References
|
|
400
245
|
|
|
401
|
-
-
|
|
402
|
-
- [WeatherKit
|
|
403
|
-
- [WeatherService](https://
|
|
404
|
-
- [WeatherAttribution](https://
|
|
405
|
-
- [WeatherQuery](https://
|
|
406
|
-
- [CurrentWeather](https://
|
|
407
|
-
- [Forecast](https://
|
|
408
|
-
- [HourWeather](https://
|
|
409
|
-
- [DayWeather](https://
|
|
410
|
-
- [WeatherAlert](https://
|
|
411
|
-
- [WeatherAvailability](https://
|
|
412
|
-
- [Fetching weather forecasts with WeatherKit](https://
|
|
246
|
+
- [references/weatherkit-patterns.md](references/weatherkit-patterns.md)
|
|
247
|
+
- [WeatherKit](https://developer.apple.com/documentation/weatherkit)
|
|
248
|
+
- [WeatherService](https://developer.apple.com/documentation/weatherkit/weatherservice)
|
|
249
|
+
- [WeatherAttribution](https://developer.apple.com/documentation/weatherkit/weatherattribution)
|
|
250
|
+
- [WeatherQuery](https://developer.apple.com/documentation/weatherkit/weatherquery)
|
|
251
|
+
- [CurrentWeather](https://developer.apple.com/documentation/weatherkit/currentweather)
|
|
252
|
+
- [Forecast](https://developer.apple.com/documentation/weatherkit/forecast)
|
|
253
|
+
- [HourWeather](https://developer.apple.com/documentation/weatherkit/hourweather)
|
|
254
|
+
- [DayWeather](https://developer.apple.com/documentation/weatherkit/dayweather)
|
|
255
|
+
- [WeatherAlert](https://developer.apple.com/documentation/weatherkit/weatheralert)
|
|
256
|
+
- [WeatherAvailability](https://developer.apple.com/documentation/weatherkit/weatheravailability)
|
|
257
|
+
- [Fetching weather forecasts with WeatherKit](https://developer.apple.com/documentation/weatherkit/fetching_weather_forecasts_with_weatherkit)
|