@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +266 -267
- package/package.json +2 -2
- package/pipeline/scripts/_notices.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +68 -68
- package/pipeline/skills/shared/README.md +70 -70
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,275 +1,229 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: swiftui-webkit
|
|
3
|
-
description: "
|
|
3
|
+
description: "Web content in SwiftUI with WebKit for SwiftUI: WebView, WebPage, observable page state, navigation policies, link interception, JavaScript calls, local HTML or data, custom URL schemes. Use when an iOS 26+ screen shows articles, detail pages, help centers, in-app docs or other embedded HTML, CSS and JavaScript, or when replacing a WKWebView wrapper. Not for OAuth or deep-link routing."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# SwiftUI
|
|
8
|
+
# WebKit for SwiftUI
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Starting with the 26 releases (iOS, iPadOS, macOS, visionOS), WebKit ships a SwiftUI
|
|
11
|
+
surface of its own: `WebView` draws web content and `WebPage` is the
|
|
12
|
+
observable model behind it. Everything below needs `import WebKit` and those
|
|
13
|
+
OS versions.
|
|
11
14
|
|
|
12
|
-
##
|
|
15
|
+
## Picking the container
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
- [Displaying Web Content](#displaying-web-content)
|
|
16
|
-
- [Loading and Observing with WebPage](#loading-and-observing-with-webpage)
|
|
17
|
-
- [Navigation Policies](#navigation-policies)
|
|
18
|
-
- [JavaScript Integration](#javascript-integration)
|
|
19
|
-
- [Local Content and Custom URL Schemes](#local-content-and-custom-url-schemes)
|
|
20
|
-
- [WebView Customization](#webview-customization)
|
|
21
|
-
- [Common Mistakes](#common-mistakes)
|
|
22
|
-
- [Review Checklist](#review-checklist)
|
|
23
|
-
- [References](#references)
|
|
24
|
-
|
|
25
|
-
## Choose the Right Web Container
|
|
26
|
-
|
|
27
|
-
Use the narrowest tool that matches the job.
|
|
28
|
-
|
|
29
|
-
| Need | Default choice |
|
|
17
|
+
| Situation | Use |
|
|
30
18
|
|---|---|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| OAuth or third-party sign-in | `ASWebAuthenticationSession` |
|
|
34
|
-
|
|
|
19
|
+
| Web content that belongs to the app, shown inside a SwiftUI screen | `WebView` with a `WebPage` |
|
|
20
|
+
| Sending the user to an outside site with Safari behaviour | `SFSafariViewController` |
|
|
21
|
+
| OAuth or any third-party sign-in | `ASWebAuthenticationSession` |
|
|
22
|
+
| Deployment target below iOS 26, or a capability only the old API has | a `WKWebView` fallback |
|
|
35
23
|
|
|
36
|
-
|
|
24
|
+
Apple's WWDC25 WebKit guidance points SwiftUI apps away from UIKit and AppKit
|
|
25
|
+
web view wrappers wherever the new API covers the need. Sign-in never runs in
|
|
26
|
+
an embedded web view.
|
|
37
27
|
|
|
38
|
-
|
|
28
|
+
## Showing a page
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Use the simple `WebView(url:)` form when the app only needs to render a URL and SwiftUI state drives navigation.
|
|
30
|
+
The shortest path renders a URL and lets SwiftUI state decide which one:
|
|
43
31
|
|
|
44
32
|
```swift
|
|
45
33
|
import SwiftUI
|
|
46
34
|
import WebKit
|
|
47
35
|
|
|
48
|
-
struct
|
|
49
|
-
let
|
|
36
|
+
struct ReleaseNotesView: View {
|
|
37
|
+
let address: URL
|
|
50
38
|
|
|
51
39
|
var body: some View {
|
|
52
|
-
WebView(url:
|
|
40
|
+
WebView(url: address)
|
|
53
41
|
}
|
|
54
42
|
}
|
|
55
43
|
```
|
|
56
44
|
|
|
57
|
-
|
|
45
|
+
As soon as you need to issue requests yourself, watch state, run
|
|
46
|
+
JavaScript or steer navigation, own a `WebPage` and pass it to
|
|
47
|
+
`WebView(page)`. Deciding this up front is cheaper than retrofitting it.
|
|
58
48
|
|
|
59
49
|
```swift
|
|
60
50
|
@Observable
|
|
61
51
|
@MainActor
|
|
62
|
-
final class
|
|
52
|
+
final class GuideModel {
|
|
63
53
|
let page = WebPage()
|
|
64
54
|
|
|
65
|
-
func
|
|
66
|
-
|
|
67
|
-
}
|
|
55
|
+
func open(_ address: URL) async throws {
|
|
56
|
+
let events = page.load(URLRequest(url: address))
|
|
57
|
+
for try await _ in events { }
|
|
68
58
|
}
|
|
69
59
|
}
|
|
70
60
|
|
|
71
|
-
struct
|
|
72
|
-
@State private var model =
|
|
73
|
-
let
|
|
61
|
+
struct GuideScreen: View {
|
|
62
|
+
@State private var model = GuideModel()
|
|
63
|
+
let start: URL
|
|
74
64
|
|
|
75
65
|
var body: some View {
|
|
76
66
|
WebView(model.page)
|
|
77
|
-
.task {
|
|
78
|
-
try? await model.load(url)
|
|
79
|
-
}
|
|
67
|
+
.task { try? await model.open(start) }
|
|
80
68
|
}
|
|
81
69
|
}
|
|
82
70
|
```
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
## Loading and Observing with WebPage
|
|
72
|
+
## Loading and observing
|
|
87
73
|
|
|
88
|
-
`WebPage` is an
|
|
74
|
+
`WebPage` is an observable class isolated to the main actor. Its load
|
|
75
|
+
methods:
|
|
89
76
|
|
|
90
|
-
|
|
91
|
-
- `load(
|
|
92
|
-
- `load(
|
|
93
|
-
|
|
94
|
-
- `load(_:mimeType:characterEncoding:baseURL:)`
|
|
77
|
+
- `load(_ request: URLRequest)` and `load(_ url: URL?)`
|
|
78
|
+
- `load(html:baseURL:)` for a string of markup
|
|
79
|
+
- `load(_:mimeType:characterEncoding:baseURL:)` for raw `Data`; the encoding
|
|
80
|
+
is a `String.Encoding` such as `.utf8`
|
|
95
81
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- `estimatedProgress`
|
|
101
|
-
- `currentNavigationEvent`
|
|
102
|
-
- `backForwardList`
|
|
82
|
+
Each returns an async sequence of navigation events that throws when the
|
|
83
|
+
navigation fails. Observable properties include `title` (a non-optional
|
|
84
|
+
`String`), `url`, `isLoading`, `estimatedProgress`, `backForwardList`,
|
|
85
|
+
`hasOnlySecureContent` and, from the SwiftUI overlay, `themeColor`.
|
|
103
86
|
|
|
104
87
|
```swift
|
|
105
|
-
struct
|
|
88
|
+
struct ArticleReader: View {
|
|
106
89
|
@State private var page = WebPage()
|
|
90
|
+
let story: URL
|
|
107
91
|
|
|
108
92
|
var body: some View {
|
|
109
93
|
WebView(page)
|
|
110
|
-
.navigationTitle(page.title
|
|
111
|
-
.overlay {
|
|
94
|
+
.navigationTitle(page.title.isEmpty ? "Article" : page.title)
|
|
95
|
+
.overlay(alignment: .top) {
|
|
112
96
|
if page.isLoading {
|
|
113
97
|
ProgressView(value: page.estimatedProgress)
|
|
114
98
|
}
|
|
115
99
|
}
|
|
116
100
|
.task {
|
|
117
101
|
do {
|
|
118
|
-
|
|
119
|
-
}
|
|
102
|
+
let events = page.load(story)
|
|
103
|
+
for try await _ in events { }
|
|
120
104
|
} catch {
|
|
121
|
-
//
|
|
105
|
+
// show an inline error state
|
|
122
106
|
}
|
|
123
107
|
}
|
|
124
108
|
}
|
|
125
109
|
}
|
|
126
110
|
```
|
|
127
111
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
for await event in page.navigations {
|
|
133
|
-
// Handle finish, redirect, or failure events.
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
See [references/loading-and-observation.md](references/loading-and-observation.md) for stronger patterns and the load-sequence examples.
|
|
112
|
+
To react to every navigation rather than sampling one property, iterate
|
|
113
|
+
`page.navigations` with `for try await`. The released SDK has no
|
|
114
|
+
`currentNavigationEvent` property; the event sequences are the way to follow
|
|
115
|
+
progress. Details are in [page loading notes](references/loading-and-observation.md).
|
|
139
116
|
|
|
140
|
-
## Navigation
|
|
117
|
+
## Navigation policy
|
|
141
118
|
|
|
142
|
-
|
|
119
|
+
A type conforming to `WebPage.NavigationDeciding` can permit, cancel or adjust
|
|
120
|
+
navigations by request or by response. Typical jobs:
|
|
143
121
|
|
|
144
|
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
- tune `NavigationPreferences`
|
|
122
|
+
- keep the app's own domains inside the web view,
|
|
123
|
+
- cancel links to other domains and hand them to `openURL`,
|
|
124
|
+
- catch callback URLs,
|
|
125
|
+
- adjust `WebPage.NavigationPreferences` for a request.
|
|
149
126
|
|
|
150
127
|
```swift
|
|
151
128
|
@MainActor
|
|
152
|
-
final class
|
|
153
|
-
var
|
|
154
|
-
|
|
155
|
-
func decidePolicy(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if url.host == "example.com" {
|
|
162
|
-
return .allow
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
urlToOpenExternally = url
|
|
129
|
+
final class DomainGate: WebPage.NavigationDeciding {
|
|
130
|
+
var leaving: URL?
|
|
131
|
+
|
|
132
|
+
func decidePolicy(for step: WebPage.NavigationAction,
|
|
133
|
+
preferences prefs: inout WebPage.NavigationPreferences)
|
|
134
|
+
async -> WKNavigationActionPolicy {
|
|
135
|
+
guard let target = step.request.url, let host = target.host() else { return .allow }
|
|
136
|
+
if host.hasSuffix("docs.example.org") { return .allow }
|
|
137
|
+
leaving = target // opened outside the app by the view
|
|
166
138
|
return .cancel
|
|
167
139
|
}
|
|
168
140
|
}
|
|
169
141
|
```
|
|
170
142
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
See [references/navigation-and-javascript.md](references/navigation-and-javascript.md) for complete patterns.
|
|
174
|
-
|
|
175
|
-
## JavaScript Integration
|
|
143
|
+
This skill covers navigation inside web content. Routing the app itself from
|
|
144
|
+
a deep link belongs to the `swiftui-navigation` skill.
|
|
176
145
|
|
|
177
|
-
|
|
146
|
+
## JavaScript
|
|
178
147
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
id: node.id,
|
|
184
|
-
text: node.textContent?.trim()
|
|
185
|
-
}));
|
|
186
|
-
"""
|
|
187
|
-
|
|
188
|
-
let result = try await page.callJavaScript(script)
|
|
189
|
-
let headings = result as? [[String: Any]] ?? []
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
You can pass values through the `arguments` dictionary and cast the returned `Any` into the Swift type you actually need.
|
|
148
|
+
`callJavaScript(_:arguments:in:contentWorld:)` runs the string as the body of
|
|
149
|
+
an async JavaScript function, so the script uses `return`. The result comes
|
|
150
|
+
back as `Any?`; cast it to the Swift shape you expect straight away, and pass
|
|
151
|
+
values through `arguments` rather than building them into the script text.
|
|
193
152
|
|
|
194
153
|
```swift
|
|
195
|
-
let
|
|
196
|
-
"return document.
|
|
197
|
-
arguments: ["
|
|
154
|
+
let raw = try await page.callJavaScript(
|
|
155
|
+
"return [...document.querySelectorAll(selector)].map(n => ({ id: n.id, text: n.textContent }))",
|
|
156
|
+
arguments: ["selector": "h2"]
|
|
198
157
|
)
|
|
158
|
+
let headings = raw as? [[String: Any]] ?? []
|
|
199
159
|
```
|
|
200
160
|
|
|
201
|
-
|
|
161
|
+
`callJavaScript` is not a message channel from the page to the app. For
|
|
162
|
+
simple one-off signals, the page can navigate to a custom callback URL that
|
|
163
|
+
the navigation decider intercepts; that is a workaround, not a full
|
|
164
|
+
replacement for `WKScriptMessageHandler`. `WebPage.Configuration` does expose
|
|
165
|
+
a `userContentController` (a `WKUserContentController`) for apps that need
|
|
166
|
+
structured script messages. See
|
|
167
|
+
[policy and script notes](references/navigation-and-javascript.md).
|
|
202
168
|
|
|
203
|
-
|
|
169
|
+
## Local content and custom schemes
|
|
204
170
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
Use `WebPage.Configuration` and `URLSchemeHandler` when the app needs bundled HTML, offline documents, or app-provided resources under a custom scheme.
|
|
171
|
+
For bundled HTML, offline documentation or resources the app generates,
|
|
172
|
+
register a `URLSchemeHandler` on a `WebPage.Configuration`:
|
|
208
173
|
|
|
209
174
|
```swift
|
|
210
|
-
var
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
let page = WebPage(configuration: configuration)
|
|
214
|
-
for try await _ in page.load(URL(string: "docs://article/welcome")!) {
|
|
175
|
+
var setup = WebPage.Configuration()
|
|
176
|
+
if let scheme = URLScheme("manual") {
|
|
177
|
+
setup.urlSchemeHandlers[scheme] = ManualFiles()
|
|
215
178
|
}
|
|
216
|
-
|
|
179
|
+
let page = WebPage(configuration: setup)
|
|
180
|
+
// later: page.load(URL(string: "manual://getting-started"))
|
|
217
181
|
```
|
|
218
182
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
-
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
-
|
|
254
|
-
-
|
|
255
|
-
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
- [ ] `WebView` and `WebPage` are the default path for iOS 26+ SwiftUI web content
|
|
260
|
-
- [ ] `ASWebAuthenticationSession` is used for auth flows instead of embedded web views
|
|
261
|
-
- [ ] `WebPage` is used whenever the app needs state observation, JS calls, or policy control
|
|
262
|
-
- [ ] Navigation policies only intercept the URLs the app actually owns or needs to reroute
|
|
263
|
-
- [ ] External domains open externally when appropriate
|
|
264
|
-
- [ ] JavaScript return values are cast defensively to concrete Swift types
|
|
265
|
-
- [ ] Custom URL schemes are used only for real app-owned resources
|
|
266
|
-
- [ ] Back/forward gestures or controls are enabled when multi-page browsing is expected
|
|
267
|
-
- [ ] The web experience adds focused native value instead of behaving like a thin browser shell
|
|
268
|
-
- [ ] Fallback to `WKWebView` is justified by deployment target or missing API needs
|
|
183
|
+
Ordinary remote content should come over HTTPS, not through a custom scheme.
|
|
184
|
+
Handler implementation and cancellation are covered in
|
|
185
|
+
[scheme handler notes](references/local-content-and-custom-schemes.md).
|
|
186
|
+
|
|
187
|
+
## View modifiers
|
|
188
|
+
|
|
189
|
+
- `webViewBackForwardNavigationGestures(_:)`: turn on swipe back and forward
|
|
190
|
+
when people will visit several pages.
|
|
191
|
+
- `findNavigator(isPresented:)`: Find in Page for long, document-like content.
|
|
192
|
+
- `webViewScrollPosition(_:)` and `webViewOnScrollGeometryChange(for:of:action:)`:
|
|
193
|
+
sync scrolling only when there is a sidebar, a table of contents or another
|
|
194
|
+
explicit navigation control.
|
|
195
|
+
|
|
196
|
+
The HIG asks for back and forward support where it helps, but an app's web
|
|
197
|
+
view should not grow into a general-purpose browser.
|
|
198
|
+
|
|
199
|
+
## Common mistakes
|
|
200
|
+
|
|
201
|
+
- Reaching for a `WKWebView` wrapper in a SwiftUI app that targets iOS 26+.
|
|
202
|
+
- Running OAuth inside an embedded web view.
|
|
203
|
+
- Starting with `WebView(url:)` and bolting on `WebPage` later once state,
|
|
204
|
+
JavaScript or navigation control turns out to be needed.
|
|
205
|
+
- Treating `callJavaScript` as if it were `WKScriptMessageHandler`.
|
|
206
|
+
- Keeping every link in the app when other domains should open outside it.
|
|
207
|
+
- Building a browser shell (address bar, tabs) around the web view.
|
|
208
|
+
- Using a custom scheme for content that should load over HTTPS.
|
|
209
|
+
- Touching a `WebPage` off the main actor; the type is `@MainActor`.
|
|
210
|
+
|
|
211
|
+
## Review checklist
|
|
212
|
+
|
|
213
|
+
- [ ] iOS 26+ screens start from `WebView` plus `WebPage`
|
|
214
|
+
- [ ] Sign-in goes through `ASWebAuthenticationSession`
|
|
215
|
+
- [ ] A `WebPage` exists wherever state, JavaScript or policy control is needed
|
|
216
|
+
- [ ] The navigation decider only intercepts URLs the app owns or reroutes
|
|
217
|
+
- [ ] Other domains open outside the app where that is the better experience
|
|
218
|
+
- [ ] JavaScript results are cast defensively
|
|
219
|
+
- [ ] Custom schemes serve only genuine app-owned resources
|
|
220
|
+
- [ ] Multi-page browsing has back and forward gestures or controls
|
|
221
|
+
- [ ] The screen offers something native and specific, not a wrapped website
|
|
222
|
+
- [ ] Each remaining `WKWebView` has a reason: an older deployment target or a missing API
|
|
269
223
|
|
|
270
224
|
## References
|
|
271
225
|
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
-
|
|
275
|
-
-
|
|
226
|
+
- [page loading notes](references/loading-and-observation.md): URL-only views, controlled loading, progress and title, navigation events, ephemeral pages, user agents
|
|
227
|
+
- [policy and script notes](references/navigation-and-javascript.md): deciders, external links, calling JavaScript, arguments, page-to-app signals
|
|
228
|
+
- [scheme handler notes](references/local-content-and-custom-schemes.md): scheme handlers, responses, bundled files, cancellation
|
|
229
|
+
- [migration notes](references/migration-and-fallbacks.md): moving off `WKWebView` wrappers, Safari and sign-in boundaries, testing
|
package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md
CHANGED
|
@@ -1,151 +1,140 @@
|
|
|
1
|
-
# Loading and
|
|
1
|
+
# Loading and observing pages
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
- Controlled `WebPage` loading
|
|
6
|
-
- Observing progress and title
|
|
7
|
-
- Observing navigation events
|
|
8
|
-
- Ephemeral pages and custom user agents
|
|
3
|
+
Part of the `swiftui-webkit` skill ([../SKILL.md](../SKILL.md)). All code
|
|
4
|
+
needs iOS 26, iPadOS 26, macOS 26 or visionOS 26 and `import WebKit`.
|
|
9
5
|
|
|
10
|
-
##
|
|
6
|
+
## The URL-only view
|
|
11
7
|
|
|
12
|
-
|
|
8
|
+
When all you need is to show a page and let people move back and forth,
|
|
9
|
+
`WebView(url:)` plus the gesture modifier is the least code:
|
|
13
10
|
|
|
14
11
|
```swift
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
struct MarketingPageView: View {
|
|
19
|
-
let url: URL
|
|
12
|
+
struct PolicyPage: View {
|
|
13
|
+
let link: URL
|
|
20
14
|
|
|
21
15
|
var body: some View {
|
|
22
|
-
WebView(url:
|
|
16
|
+
WebView(url: link)
|
|
23
17
|
.webViewBackForwardNavigationGestures(.enabled)
|
|
24
18
|
}
|
|
25
19
|
}
|
|
26
20
|
```
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## Controlled `WebPage` loading
|
|
22
|
+
## Loading through a WebPage
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
A model that owns the page can keep the last failure for the UI:
|
|
33
25
|
|
|
34
26
|
```swift
|
|
35
27
|
@Observable
|
|
36
28
|
@MainActor
|
|
37
|
-
final class
|
|
29
|
+
final class HelpCenterModel {
|
|
38
30
|
let page = WebPage()
|
|
39
|
-
var
|
|
31
|
+
var failure: Error?
|
|
40
32
|
|
|
41
|
-
func
|
|
33
|
+
func show(_ address: URL) async {
|
|
34
|
+
failure = nil
|
|
42
35
|
do {
|
|
43
|
-
for try await _ in page.load(URLRequest(url:
|
|
44
|
-
}
|
|
36
|
+
for try await _ in page.load(URLRequest(url: address)) { }
|
|
45
37
|
} catch {
|
|
46
|
-
|
|
38
|
+
failure = error
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
41
|
}
|
|
50
42
|
```
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
struct ArticleDetailView: View {
|
|
54
|
-
@State private var model = ArticleModel()
|
|
55
|
-
let url: URL
|
|
44
|
+
The other load entry points return the same kind of event sequence:
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
46
|
+
```swift
|
|
47
|
+
_ = page.load(address)
|
|
48
|
+
_ = page.load(html: "<h1>Offline</h1><p>Try again later.</p>") // baseURL defaults to about:blank
|
|
49
|
+
_ = page.load(markupData,
|
|
50
|
+
mimeType: "text/html",
|
|
51
|
+
characterEncoding: .utf8,
|
|
52
|
+
baseURL: bundleFolder)
|
|
64
53
|
```
|
|
65
54
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
- `for try await _ in page.load(data, mimeType: "text/html", characterEncoding: "utf-8", baseURL: baseURL) { }`
|
|
55
|
+
Iterate the returned sequence (or ignore it) depending on whether the caller
|
|
56
|
+
cares when the load ends. `characterEncoding` takes a `String.Encoding`, not a
|
|
57
|
+
string like `"utf-8"`.
|
|
70
58
|
|
|
71
|
-
##
|
|
59
|
+
## Progress, title and other state
|
|
72
60
|
|
|
73
|
-
`
|
|
61
|
+
Besides `title`, `url`, `isLoading`, `estimatedProgress` and
|
|
62
|
+
`backForwardList`, a page reports `themeColor` (the page's theme colour, if
|
|
63
|
+
any) and `hasOnlySecureContent`.
|
|
74
64
|
|
|
75
65
|
```swift
|
|
76
|
-
struct
|
|
77
|
-
@State private var
|
|
66
|
+
struct DocsPane: View {
|
|
67
|
+
@State private var model = HelpCenterModel()
|
|
68
|
+
let home: URL
|
|
78
69
|
|
|
79
70
|
var body: some View {
|
|
80
|
-
WebView(page)
|
|
81
|
-
.navigationTitle(page.title
|
|
71
|
+
WebView(model.page)
|
|
72
|
+
.navigationTitle(model.page.title)
|
|
73
|
+
.toolbarBackground(model.page.themeColor ?? .clear, for: .navigationBar)
|
|
82
74
|
.overlay(alignment: .top) {
|
|
83
|
-
if page.isLoading {
|
|
84
|
-
ProgressView(value: page.estimatedProgress)
|
|
85
|
-
.padding()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
.task {
|
|
89
|
-
do {
|
|
90
|
-
for try await _ in page.load(URLRequest(url: URL(string: "https://example.com/docs")!)) {
|
|
91
|
-
}
|
|
92
|
-
} catch {
|
|
93
|
-
// Handle load failure.
|
|
75
|
+
if model.page.isLoading {
|
|
76
|
+
ProgressView(value: model.page.estimatedProgress)
|
|
77
|
+
.padding(.horizontal)
|
|
94
78
|
}
|
|
95
79
|
}
|
|
80
|
+
.task { await model.show(home) }
|
|
96
81
|
}
|
|
97
82
|
}
|
|
98
83
|
```
|
|
99
84
|
|
|
100
|
-
|
|
101
|
-
- `title`
|
|
102
|
-
- `url`
|
|
103
|
-
- `isLoading`
|
|
104
|
-
- `estimatedProgress`
|
|
105
|
-
- `themeColor`
|
|
106
|
-
- `hasOnlySecureContent`
|
|
107
|
-
- `backForwardList`
|
|
108
|
-
|
|
109
|
-
## Observing navigation events
|
|
85
|
+
## Following navigation events
|
|
110
86
|
|
|
111
|
-
|
|
87
|
+
`load` returns the events of that one navigation; `page.navigations` delivers
|
|
88
|
+
the events of every navigation the page makes, including link taps. Both are
|
|
89
|
+
throwing sequences. The event cases are `.startedProvisionalNavigation`,
|
|
90
|
+
`.receivedServerRedirect`, `.committed` and `.finished`. Failures are not
|
|
91
|
+
events: they arrive as thrown errors, typically a `WebPage.NavigationError`
|
|
92
|
+
such as `.failedProvisionalNavigation(_:)`, `.webContentProcessTerminated`
|
|
93
|
+
or `.pageClosed`.
|
|
112
94
|
|
|
113
95
|
```swift
|
|
114
96
|
@MainActor
|
|
115
|
-
func
|
|
116
|
-
|
|
117
|
-
for await event in page.navigations {
|
|
97
|
+
func watch(_ page: WebPage) async {
|
|
98
|
+
do {
|
|
99
|
+
for try await event in page.navigations {
|
|
118
100
|
switch event {
|
|
119
101
|
case .finished:
|
|
120
|
-
|
|
121
|
-
case .failed(let error), .failedProvisionalNavigation(let error):
|
|
122
|
-
print("Navigation failed: \(error)")
|
|
102
|
+
await collectHeadings(from: page) // follow-up work goes here
|
|
123
103
|
default:
|
|
124
104
|
break
|
|
125
105
|
}
|
|
126
106
|
}
|
|
107
|
+
} catch WebPage.NavigationError.failedProvisionalNavigation(let reason) {
|
|
108
|
+
report(reason)
|
|
109
|
+
} catch {
|
|
110
|
+
report(error)
|
|
127
111
|
}
|
|
128
112
|
}
|
|
129
113
|
```
|
|
130
114
|
|
|
131
|
-
|
|
115
|
+
The finished event is the right moment for work that needs the loaded
|
|
116
|
+
document, such as reading its headings. For lightweight UI, the observable
|
|
117
|
+
properties (`isLoading`, `estimatedProgress`) are usually enough; there is no
|
|
118
|
+
separate "current event" property.
|
|
132
119
|
|
|
133
|
-
##
|
|
120
|
+
## Throwaway pages and custom user agents
|
|
134
121
|
|
|
135
|
-
|
|
122
|
+
For a quick metadata fetch or an isolated session, configure a page that
|
|
123
|
+
keeps nothing around:
|
|
136
124
|
|
|
137
125
|
```swift
|
|
138
126
|
@MainActor
|
|
139
|
-
func
|
|
140
|
-
var
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
let page = WebPage(configuration:
|
|
146
|
-
page.customUserAgent = "
|
|
127
|
+
func makeScratchPage() -> WebPage {
|
|
128
|
+
var setup = WebPage.Configuration()
|
|
129
|
+
setup.loadsSubresources = false
|
|
130
|
+
setup.defaultNavigationPreferences.allowsContentJavaScript = false
|
|
131
|
+
setup.websiteDataStore = .nonPersistent()
|
|
132
|
+
|
|
133
|
+
let page = WebPage(configuration: setup)
|
|
134
|
+
page.customUserAgent = "ExampleReader/2.1"
|
|
147
135
|
return page
|
|
148
136
|
}
|
|
149
137
|
```
|
|
150
138
|
|
|
151
|
-
|
|
139
|
+
A non-persistent data store means no shared cookies and no long-lived website
|
|
140
|
+
data, so each such page is its own sealed session.
|