@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +266 -267
- package/package.json +2 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +68 -68
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md
CHANGED
|
@@ -1,120 +1,180 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Data handoff, notifications and location
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Moving state to the full app, signing people in once, notifying them within
|
|
4
|
+
the clip's window, and proving they are where the code is. Summary in
|
|
5
|
+
`../SKILL.md`.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Handing data to the full app
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- [Ephemeral Notifications](#ephemeral-notifications)
|
|
11
|
-
- [Location Confirmation](#location-confirmation)
|
|
12
|
-
- [Lifecycle and Ephemeral State](#lifecycle-and-ephemeral-state)
|
|
13
|
-
|
|
14
|
-
## Data Migration to Full App
|
|
15
|
-
|
|
16
|
-
When a user installs the full app, it replaces the App Clip. Use a **shared App Group container** for non-secret data the full app needs:
|
|
9
|
+
When someone installs the full app it replaces the clip. Anything non-secret
|
|
10
|
+
the full app should pick up goes into a shared App Group container. Add the
|
|
11
|
+
App Groups capability to both targets with the same group identifier.
|
|
17
12
|
|
|
18
13
|
```swift
|
|
19
|
-
|
|
14
|
+
import Foundation
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
forSecurityApplicationGroupIdentifier: "group.com.example.myapp.shared"
|
|
25
|
-
) else { return }
|
|
26
|
-
|
|
27
|
-
let data = try JSONEncoder().encode(order)
|
|
28
|
-
let fileURL = containerURL.appendingPathComponent("pending-order.json")
|
|
29
|
-
try data.write(to: fileURL)
|
|
16
|
+
struct PendingTicket: Codable {
|
|
17
|
+
let seat: String
|
|
18
|
+
let showTime: Date
|
|
30
19
|
}
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
21
|
+
enum SharedDrop {
|
|
22
|
+
static let group = "group.org.example.tickets"
|
|
23
|
+
|
|
24
|
+
static func file() -> URL? {
|
|
25
|
+
FileManager.default
|
|
26
|
+
.containerURL(forSecurityApplicationGroupIdentifier: group)?
|
|
27
|
+
.appending(path: "pending-ticket.json")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static func save(_ ticket: PendingTicket) throws {
|
|
31
|
+
guard let target = file() else { return }
|
|
32
|
+
try JSONEncoder().encode(ticket).write(to: target, options: .atomic)
|
|
33
|
+
}
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
static func load() -> PendingTicket? {
|
|
36
|
+
guard let source = file(), FileManager.default.fileExists(atPath: source.path()) else {
|
|
37
|
+
return nil
|
|
38
|
+
}
|
|
39
|
+
guard let bytes = try? Data(contentsOf: source) else { return nil }
|
|
40
|
+
return try? JSONDecoder().decode(PendingTicket.self, from: bytes)
|
|
41
|
+
}
|
|
42
42
|
}
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
The clip calls `save`; the full app calls `load` on first launch. Both return
|
|
46
|
+
early when the container is unavailable (for example, a misconfigured
|
|
47
|
+
entitlement).
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
For small values (identifiers, timestamps, choices, cart metadata), a shared
|
|
50
|
+
defaults suite is enough:
|
|
48
51
|
|
|
49
52
|
```swift
|
|
50
|
-
|
|
51
|
-
shared?.set(orderID, forKey: "pendingOrderID")
|
|
52
|
-
```
|
|
53
|
+
import Foundation
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
func rememberPendingOrder(_ orderID: String) {
|
|
56
|
+
UserDefaults(suiteName: "group.org.example.tickets")?.set(orderID, forKey: "pendingOrderID")
|
|
57
|
+
}
|
|
58
|
+
```
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
Any target that carries the same App Group entitlement can read and write this
|
|
61
|
+
data. Treat it as a convenience channel, not a trust boundary, and keep
|
|
62
|
+
secrets out of it.
|
|
63
|
+
|
|
64
|
+
## Keychain
|
|
65
|
+
|
|
66
|
+
- From iOS 15.4 the full app can read keychain items the clip created. The
|
|
67
|
+
system uses the association entitlements to make sure only the matching
|
|
68
|
+
full app gets them: `com.apple.developer.parent-application-identifiers` on
|
|
69
|
+
the clip and `com.apple.developer.associated-appclip-app-identifiers` on the
|
|
70
|
+
full app (Xcode adds the latter when you archive).
|
|
71
|
+
- It only works in that direction. The clip cannot read items the full app
|
|
72
|
+
stored.
|
|
73
|
+
- On iOS 15.3 and earlier the full app cannot see the clip's items at all;
|
|
74
|
+
use a shared container value or Sign in with Apple instead.
|
|
75
|
+
- Because people install, delete and reinstall, both targets may end up
|
|
76
|
+
writing the same logical item. Give clip-created items a distinct label,
|
|
77
|
+
service or account name (for example a `kSecAttrLabel` of `tickets-clip`),
|
|
78
|
+
and when migrating, detect duplicates, decide which copy wins and delete the
|
|
79
|
+
rest.
|
|
59
80
|
|
|
60
81
|
## Sign in with Apple
|
|
61
82
|
|
|
62
|
-
Store the `ASAuthorizationAppleIDCredential.user`
|
|
83
|
+
Store the stable user identifier from `ASAuthorizationAppleIDCredential.user`
|
|
84
|
+
in the shared container. The full app checks that it is still valid instead
|
|
85
|
+
of asking the person to sign in again:
|
|
63
86
|
|
|
64
87
|
```swift
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
88
|
+
import AuthenticationServices
|
|
89
|
+
|
|
90
|
+
func adoptClipAccount(userID: String, onValid: @escaping @Sendable () -> Void) {
|
|
91
|
+
ASAuthorizationAppleIDProvider().getCredentialState(forUserID: userID) { state, _ in
|
|
92
|
+
if state == .authorized {
|
|
93
|
+
onValid()
|
|
94
|
+
}
|
|
69
95
|
}
|
|
70
96
|
}
|
|
71
97
|
```
|
|
72
98
|
|
|
73
|
-
|
|
99
|
+
Anything other than `.authorized` (revoked, not found, transferred) means the
|
|
100
|
+
full app runs its normal sign-in.
|
|
74
101
|
|
|
75
|
-
|
|
102
|
+
## Ephemeral notifications
|
|
76
103
|
|
|
77
|
-
|
|
104
|
+
- Add `NSAppClip` (a dictionary) to the clip's Info.plist and set
|
|
105
|
+
`NSAppClipRequestEphemeralUserNotification` to `true` inside it.
|
|
106
|
+
- The clip may then schedule or receive notifications for up to 8 hours after
|
|
107
|
+
each launch.
|
|
108
|
+
- The App Clip card mentions this and people can turn it off there, so check
|
|
109
|
+
the current status first:
|
|
78
110
|
|
|
79
|
-
|
|
80
|
-
|
|
111
|
+
```swift
|
|
112
|
+
import UserNotifications
|
|
113
|
+
|
|
114
|
+
func scheduleIfAllowed(_ request: UNNotificationRequest) async throws {
|
|
115
|
+
let center = UNUserNotificationCenter.current()
|
|
116
|
+
guard await center.notificationSettings().authorizationStatus == .ephemeral else { return }
|
|
117
|
+
try await center.add(request)
|
|
118
|
+
}
|
|
119
|
+
```
|
|
81
120
|
|
|
82
|
-
|
|
121
|
+
- A clip whose job lasts longer than a day can ask for regular notification
|
|
122
|
+
permission, but a refusal also removes the 8-hour ephemeral window.
|
|
123
|
+
- Tapping a notification relaunches the clip without an invocation URL.
|
|
124
|
+
Handle that in the clip and in the full app.
|
|
125
|
+
- A clip that serves several places or businesses must tell the system which
|
|
126
|
+
experience a notification belongs to. Remote pushes set `target-content-id`
|
|
127
|
+
in the APNs payload; local notifications set
|
|
128
|
+
`UNNotificationContent.targetContentIdentifier`. The value is a URL that
|
|
129
|
+
matches the relevant advanced experience, as specific as possible, not an
|
|
130
|
+
arbitrary token.
|
|
83
131
|
|
|
84
|
-
|
|
132
|
+
## Location confirmation
|
|
133
|
+
|
|
134
|
+
`APActivationPayload` (iOS 14+) confirms that a physical invocation (App Clip
|
|
135
|
+
Code, NFC tag or QR code) happened inside a region you name, without giving
|
|
136
|
+
the clip ongoing location access. The region's radius may be at most 500 m.
|
|
85
137
|
|
|
86
138
|
```swift
|
|
87
139
|
import AppClip
|
|
88
140
|
import CoreLocation
|
|
89
141
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@unknown default:
|
|
105
|
-
break
|
|
106
|
-
}
|
|
142
|
+
enum BoothCheck: Sendable {
|
|
143
|
+
case confirmed, elsewhere, linkMismatch, notAllowed, unknown
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
func confirmAtBooth(_ activity: NSUserActivity, booth: CLLocationCoordinate2D,
|
|
147
|
+
done: @escaping @Sendable (BoothCheck) -> Void) {
|
|
148
|
+
guard let payload = activity.appClipActivationPayload else {
|
|
149
|
+
done(.unknown)
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
let area = CLCircularRegion(center: booth, radius: 80, identifier: "booth")
|
|
153
|
+
payload.confirmAcquired(in: area) { inside, failure in
|
|
154
|
+
guard let failure else {
|
|
155
|
+
done(inside ? .confirmed : .elsewhere)
|
|
107
156
|
return
|
|
108
157
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
158
|
+
guard let reason = failure as? APActivationPayloadError else {
|
|
159
|
+
done(.unknown)
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
switch reason.code {
|
|
163
|
+
case .doesNotMatch: done(.linkMismatch)
|
|
164
|
+
case .disallowed: done(.notAllowed)
|
|
165
|
+
@unknown default: done(.unknown)
|
|
112
166
|
}
|
|
113
167
|
}
|
|
114
168
|
}
|
|
115
169
|
```
|
|
116
170
|
|
|
117
|
-
|
|
171
|
+
Route into the location-specific flow only on `.confirmed`.
|
|
172
|
+
|
|
173
|
+
- `.doesNotMatch`: the invocation URL does not match the registered App Clip URL.
|
|
174
|
+
- `.disallowed`: the person denied location, or the invocation did not come
|
|
175
|
+
from an NFC tag or visual code.
|
|
176
|
+
|
|
177
|
+
Enable it in the clip target's Info.plist only:
|
|
118
178
|
|
|
119
179
|
```xml
|
|
120
180
|
<key>NSAppClip</key>
|
|
@@ -124,12 +184,19 @@ Enable location confirmation in the App Clip target's `Info.plist`, not the full
|
|
|
124
184
|
</dict>
|
|
125
185
|
```
|
|
126
186
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
187
|
+
The system answers whether the invocation happened in the region; the App
|
|
188
|
+
Clip card tells the person the clip can verify their location.
|
|
189
|
+
|
|
190
|
+
## Lifecycle and short-lived state
|
|
191
|
+
|
|
192
|
+
- No Home Screen icon. Clips show up in the App Library and in recently used
|
|
193
|
+
apps.
|
|
194
|
+
- The system may delete an unused clip, with its data, after a period it
|
|
195
|
+
decides.
|
|
196
|
+
- Nothing guarantees local state survives. Move important non-secret data to
|
|
197
|
+
the shared container or a server.
|
|
198
|
+
- Relaunching from the App Library reuses the last invocation URL; relaunching
|
|
199
|
+
from the app switcher has none, so restore saved state.
|
|
200
|
+
- Location is limited to When In Use. Authorization is short-lived and resets
|
|
201
|
+
automatically (the next day at 4:00 a.m.); continuous access cannot be
|
|
202
|
+
requested.
|
|
@@ -1,125 +1,177 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Routing and experiences
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
How an App Clip learns what to show, how App Store Connect maps URLs to
|
|
4
|
+
experiences, which sources can launch a clip, and how to test it. Summary in
|
|
5
|
+
`../SKILL.md`.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Handling the invocation URL
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- [Safari Smart App Banner](#safari-smart-app-banner)
|
|
11
|
-
- [Local Testing](#local-testing)
|
|
12
|
-
|
|
13
|
-
## Invocation URL Handling
|
|
14
|
-
|
|
15
|
-
App Clips receive an `NSUserActivity` of type `NSUserActivityTypeBrowsingWeb`. Route from the invocation URL and keep the same router available to the full app.
|
|
9
|
+
Everything starts from the invocation URL. Parse it once, in a router that
|
|
10
|
+
the clip and the full app both compile, because the full app replaces the
|
|
11
|
+
clip after installation and must answer the same links.
|
|
16
12
|
|
|
17
13
|
### SwiftUI
|
|
18
14
|
|
|
19
15
|
```swift
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
import Observation
|
|
17
|
+
import SwiftUI
|
|
18
|
+
|
|
19
|
+
@MainActor
|
|
20
|
+
@Observable
|
|
21
|
+
final class VisitRouter {
|
|
22
|
+
var venueID: String?
|
|
23
|
+
|
|
24
|
+
func open(_ link: URL) {
|
|
25
|
+
let parts = URLComponents(url: link, resolvingAgainstBaseURL: true)
|
|
26
|
+
venueID = parts?.queryItems?.first { $0.name == "venue" }?.value
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
struct VisitScreen: View {
|
|
31
|
+
let router: VisitRouter
|
|
32
|
+
|
|
33
|
+
var body: some View {
|
|
34
|
+
Group {
|
|
35
|
+
if let venue = router.venueID {
|
|
36
|
+
Text("Checking in at \(venue)")
|
|
37
|
+
} else {
|
|
38
|
+
ProgressView()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
struct CoffeeClip: App {
|
|
45
|
+
@State private var router = VisitRouter()
|
|
46
|
+
|
|
22
47
|
var body: some Scene {
|
|
23
48
|
WindowGroup {
|
|
24
|
-
|
|
49
|
+
VisitScreen(router: router)
|
|
25
50
|
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
|
|
26
|
-
|
|
51
|
+
if let link = activity.webpageURL {
|
|
52
|
+
router.open(link)
|
|
53
|
+
}
|
|
27
54
|
}
|
|
28
55
|
}
|
|
29
56
|
}
|
|
30
|
-
|
|
31
|
-
private func handleInvocation(_ activity: NSUserActivity) {
|
|
32
|
-
guard let url = activity.webpageURL,
|
|
33
|
-
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)
|
|
34
|
-
else { return }
|
|
35
|
-
|
|
36
|
-
let locationID = components.queryItems?
|
|
37
|
-
.first(where: { $0.name == "location" })?.value
|
|
38
|
-
|
|
39
|
-
routeToLocation(id: locationID)
|
|
40
|
-
}
|
|
41
57
|
}
|
|
42
58
|
```
|
|
43
59
|
|
|
60
|
+
In the real target the `App` type carries `@main`. Copy is a literal here for
|
|
61
|
+
brevity; ship localized strings.
|
|
62
|
+
|
|
44
63
|
### UIKit scenes
|
|
45
64
|
|
|
46
|
-
|
|
65
|
+
```swift
|
|
66
|
+
import UIKit
|
|
47
67
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- Relaunch warning: `scene(_:willContinueUserActivityWithType:)` can tell you a continuation is coming, but it does not provide the activity or URL.
|
|
68
|
+
final class ClipSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|
69
|
+
var window: UIWindow?
|
|
51
70
|
|
|
52
|
-
|
|
71
|
+
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
|
|
72
|
+
options connectionOptions: UIScene.ConnectionOptions) {
|
|
73
|
+
let browsing = connectionOptions.userActivities.first { $0.activityType == NSUserActivityTypeBrowsingWeb }
|
|
74
|
+
if let link = browsing?.webpageURL {
|
|
75
|
+
route(link)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
53
78
|
|
|
54
|
-
|
|
79
|
+
func scene(_ scene: UIScene, continue incoming: NSUserActivity) {
|
|
80
|
+
if incoming.activityType == NSUserActivityTypeBrowsingWeb, let link = incoming.webpageURL {
|
|
81
|
+
route(link)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
55
84
|
|
|
56
|
-
|
|
85
|
+
private func route(_ link: URL) {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
57
89
|
|
|
58
|
-
|
|
90
|
+
- Cold launch: the activity is in `connectionOptions.userActivities` inside
|
|
91
|
+
`scene(_:willConnectTo:options:)`.
|
|
92
|
+
- Already running: `scene(_:continue:)` delivers it.
|
|
93
|
+
- `scene(_:willContinueUserActivityWithType:)` fires before either and has
|
|
94
|
+
neither the activity nor its URL; use it at most to show a loading state.
|
|
59
95
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- App Store Connect generates a **default App Clip link** with an `appclip.apple.com` URL.
|
|
63
|
-
- Supports web and shared-link invocation; QR and NFC can encode links, but count as physical triggers for size-policy decisions.
|
|
96
|
+
The rule that ties this together: every invocation URL the clip supports must
|
|
97
|
+
also work in the full app.
|
|
64
98
|
|
|
65
|
-
|
|
99
|
+
## App Store Connect experiences
|
|
66
100
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- App Clip Codes require the short version of the demo App Clip link.
|
|
70
|
-
- Does not replace Maps, Smart App Banners, or website App Clip cards.
|
|
71
|
-
- Can use the larger current App Clip binary limit.
|
|
72
|
-
- Cannot contain URL parameters.
|
|
101
|
+
Experiences are set up in App Store Connect after you upload a build that
|
|
102
|
+
contains the clip.
|
|
73
103
|
|
|
74
|
-
###
|
|
104
|
+
### Default experience
|
|
75
105
|
|
|
76
|
-
- Required for
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
106
|
+
- Required for every clip.
|
|
107
|
+
- It needs a header image, a subtitle, and the verb shown on the action
|
|
108
|
+
button.
|
|
109
|
+
- App Store Connect creates the default link for you, hosted on
|
|
110
|
+
`appclip.apple.com`.
|
|
111
|
+
- That link covers web and shared-link invocations. QR codes and NFC tags may
|
|
112
|
+
encode it, but they then count as physical invocations for the size policy.
|
|
81
113
|
|
|
82
|
-
###
|
|
114
|
+
### Demo link
|
|
83
115
|
|
|
84
|
-
|
|
116
|
+
- Generated automatically for demo versions of an app.
|
|
117
|
+
- Works from NFC tags and QR codes, so physical invocations can be tested.
|
|
118
|
+
- App Clip Codes need the short form of the demo link.
|
|
119
|
+
- It does not stand in for Maps, Smart App Banners or App Clip cards on a
|
|
120
|
+
website.
|
|
121
|
+
- It qualifies for the larger current size limit.
|
|
122
|
+
- It cannot carry URL parameters.
|
|
85
123
|
|
|
86
|
-
|
|
87
|
-
appclips:example.com
|
|
88
|
-
```
|
|
124
|
+
### Advanced experiences
|
|
89
125
|
|
|
90
|
-
|
|
126
|
+
- Needed for Maps, for associating the clip with a location, for per-location
|
|
127
|
+
card images and for exact routing at a physical place.
|
|
128
|
+
- The normal route for App Clip Codes once they are printed for real use.
|
|
129
|
+
- Every one carries its own URL, card image and card text.
|
|
130
|
+
- Registered URLs match by prefix, so one entry can serve many sub-paths
|
|
131
|
+
(`https://example.com/venue/` covers `https://example.com/venue/12/table/4`).
|
|
132
|
+
- When there are many (a chain of stores, say), create and update them
|
|
133
|
+
through the App Store Connect API rather than by hand.
|
|
91
134
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
| **Safari Smart App Banners** | Associate the App Clip with the website and add the banner meta tag |
|
|
98
|
-
| **Maps** | Advanced experience with place association |
|
|
99
|
-
| **Messages** | Share invocation URL as text; demo links have limited preview behavior |
|
|
100
|
-
| **Siri Suggestions** | Location-based; requires advanced experience for location suggestions |
|
|
101
|
-
| **Other apps with Link Presentation** | Can surface App Clip experiences through rich link metadata |
|
|
102
|
-
| **Other apps using SwiftUI `Link` / `UIApplication.open(_:)`** | Open default, associated-website, or demo-link URLs; advanced App Clip experiences are not supported for this launch path |
|
|
135
|
+
### Associated domains
|
|
136
|
+
|
|
137
|
+
Custom URLs and advanced experiences need the entry `appclips:example.com` in
|
|
138
|
+
the Associated Domains of both the clip and the full app, and an
|
|
139
|
+
association file on that domain that names the clip.
|
|
103
140
|
|
|
104
|
-
##
|
|
141
|
+
## Invocation sources
|
|
105
142
|
|
|
106
|
-
|
|
143
|
+
| Source | How it reaches the clip |
|
|
144
|
+
|---|---|
|
|
145
|
+
| App Clip Codes | Advanced experience in production; short demo link for demo codes. Can embed NFC or be scan-only |
|
|
146
|
+
| NFC tags | URL stored in an NDEF payload; a physical invocation for size purposes |
|
|
147
|
+
| QR codes | URL encoded in the code; a physical invocation for size purposes |
|
|
148
|
+
| Safari Smart App Banner | Link the clip to the site, then put the banner tag in the page head |
|
|
149
|
+
| Maps | An advanced experience tied to a place |
|
|
150
|
+
| Messages | The invocation URL shared as text; demo links preview in a limited way |
|
|
151
|
+
| Siri Suggestions | Location-based; suggestions tied to a place need an advanced experience |
|
|
152
|
+
| Other apps with Link Presentation | Rich link metadata can surface the experience |
|
|
153
|
+
| Other apps opening a URL (`Link`, `UIApplication.open(_:)`) | Works for the default link, links on the associated website and the demo link; this path cannot reach advanced experiences |
|
|
154
|
+
|
|
155
|
+
## Smart App Banner
|
|
107
156
|
|
|
108
157
|
```html
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
158
|
+
<head>
|
|
159
|
+
<meta content="app-id=987654321, app-clip-bundle-id=org.example.Tickets.Clip, app-clip-display=card"
|
|
160
|
+
name="apple-itunes-app">
|
|
161
|
+
</head>
|
|
112
162
|
```
|
|
113
163
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
164
|
+
- With `app-clip-display=card`, iOS 15 and later present the full card, both
|
|
165
|
+
in Safari and inside `SFSafariViewController`.
|
|
166
|
+
- `app-argument` belongs to full-app Smart App Banners; it is not documented
|
|
167
|
+
for App Clip launches, so routing must come from the URL itself.
|
|
117
168
|
|
|
118
|
-
|
|
169
|
+
## Local testing
|
|
119
170
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// or register a Local Experience in Settings → Developer → Local Experiences.
|
|
123
|
-
```
|
|
171
|
+
Test the path a real invocation takes. Running the clip scheme directly from
|
|
172
|
+
Xcode can skip it and hide routing bugs. Two options:
|
|
124
173
|
|
|
125
|
-
|
|
174
|
+
- In the clip scheme's Run settings, add an environment variable named
|
|
175
|
+
`_XCAppClipURL` whose value is the URL to simulate.
|
|
176
|
+
- Register a Local Experience on the device under Settings > Developer >
|
|
177
|
+
Local Experiences, then invoke it with a QR code, NFC tag or link.
|