@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,500 +1,314 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: swift-charts
|
|
3
|
-
description: "
|
|
3
|
+
description: "Swift Charts: bar, line, area, point, pie, donut, iOS 26 3D charts (Chart3D, SurfacePlot), axes, scales, legends, annotations, scrolling, selection, foregroundStyle grouping, vectorized BarPlot/LinePlot/AreaPlot/PointPlot function plots, Gantt, heat maps, sparklines, grouped bars, threshold lines, spatial plots. Use when implementing, reviewing or improving a SwiftUI chart. Not for map annotations, navigation, data loading or full VoiceOver audits."
|
|
4
4
|
metadata:
|
|
5
|
-
source:
|
|
5
|
+
source: multi-agent-pipeline
|
|
6
6
|
---
|
|
7
|
-
# Swift Charts
|
|
8
|
-
|
|
9
|
-
Build data visualizations with Swift Charts targeting iOS 26+. Compose marks
|
|
10
|
-
inside `Chart` or `Chart3D`, configure axes and scales with view modifiers, and
|
|
11
|
-
use vectorized plots or 3D plots when the data calls for them.
|
|
12
|
-
|
|
13
|
-
See [references/charts-patterns.md](references/charts-patterns.md) for extended patterns, 3D charts, accessibility, and theming guidance.
|
|
14
|
-
|
|
15
|
-
## Contents
|
|
16
|
-
|
|
17
|
-
- [Workflow](#workflow)
|
|
18
|
-
- [Chart Container](#chart-container)
|
|
19
|
-
- [Mark Types](#mark-types)
|
|
20
|
-
- [Axis Customization](#axis-customization)
|
|
21
|
-
- [Scale Configuration](#scale-configuration)
|
|
22
|
-
- [Foreground Style and Encoding](#foreground-style-and-encoding)
|
|
23
|
-
- [Selection (iOS 17+)](#selection-ios-17)
|
|
24
|
-
- [Scrollable Charts (iOS 17+)](#scrollable-charts-ios-17)
|
|
25
|
-
- [Annotations](#annotations)
|
|
26
|
-
- [Legend](#legend)
|
|
27
|
-
- [Vectorized Plots (iOS 18+)](#vectorized-plots-ios-18)
|
|
28
|
-
- [3D Charts (iOS 26+)](#3d-charts-ios-26)
|
|
29
|
-
- [Common Mistakes](#common-mistakes)
|
|
30
|
-
- [Review Checklist](#review-checklist)
|
|
31
|
-
- [References](#references)
|
|
32
|
-
|
|
33
|
-
## Workflow
|
|
34
7
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
1. Define data as an `Identifiable` struct or use `id:` key path.
|
|
38
|
-
2. Choose mark type(s): `BarMark`, `LineMark`, `PointMark`, `AreaMark`,
|
|
39
|
-
`RuleMark`, `RectangleMark`, `SectorMark`, or `SurfacePlot`.
|
|
40
|
-
3. Wrap 2D marks in `Chart`; use `Chart3D` only for real spatial or surface data.
|
|
41
|
-
4. Encode visual channels: `.foregroundStyle(by:)`, `.symbol(by:)`, `.lineStyle(by:)`.
|
|
42
|
-
5. Configure axes with `.chartXAxis` / `.chartYAxis`.
|
|
43
|
-
6. Set scale domains with `.chartXScale(domain:)` / `.chartYScale(domain:)`.
|
|
44
|
-
7. Add selection, scrolling, or annotations as needed.
|
|
45
|
-
8. For 1000+ 2D data points, use vectorized plots (`BarPlot`, `LinePlot`, etc.).
|
|
8
|
+
# Swift Charts
|
|
46
9
|
|
|
47
|
-
|
|
10
|
+
Baseline: iOS 26. Marks go inside `Chart` (or `Chart3D`), axes and scales are
|
|
11
|
+
view modifiers, and vectorized or 3D plots are used when the data calls for
|
|
12
|
+
them. Each API below lists its first release.
|
|
48
13
|
|
|
49
|
-
|
|
14
|
+
Extended recipes: [chart patterns](references/charts-patterns.md).
|
|
50
15
|
|
|
51
|
-
|
|
16
|
+
Outside this skill: map annotations and overlays (MapKit guidance), navigation
|
|
17
|
+
and deep links (`swiftui-navigation`), loading data and model ownership
|
|
18
|
+
(networking, concurrency and SwiftUI architecture skills), full VoiceOver
|
|
19
|
+
audits (`ios-accessibility`). Chart-level labels, colour, Dynamic Type and
|
|
20
|
+
audio graphs stay here.
|
|
52
21
|
|
|
53
|
-
|
|
54
|
-
// Data-driven init (single-series)
|
|
55
|
-
Chart(sales) { item in
|
|
56
|
-
BarMark(x: .value("Month", item.month), y: .value("Revenue", item.revenue))
|
|
57
|
-
}
|
|
22
|
+
## Workflow
|
|
58
23
|
|
|
59
|
-
|
|
60
|
-
Chart {
|
|
61
|
-
ForEach(seriesA) { item in
|
|
62
|
-
LineMark(x: .value("Date", item.date), y: .value("Value", item.value))
|
|
63
|
-
.foregroundStyle(.blue)
|
|
64
|
-
}
|
|
65
|
-
RuleMark(y: .value("Target", 500))
|
|
66
|
-
.foregroundStyle(.red)
|
|
67
|
-
}
|
|
24
|
+
Building a chart:
|
|
68
25
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
26
|
+
1. Make each data point an `Identifiable` value, or give the chart an `id:`
|
|
27
|
+
key path.
|
|
28
|
+
2. Choose marks: `BarMark`, `LineMark`, `PointMark`, `AreaMark`, `RuleMark`,
|
|
29
|
+
`RectangleMark`, `SectorMark`, or `SurfacePlot` for surfaces.
|
|
30
|
+
3. Flat marks belong in `Chart`. Reserve `Chart3D` for data that truly has
|
|
31
|
+
three spatial dimensions or describes a surface.
|
|
32
|
+
4. Encode extra dimensions with `.foregroundStyle(by:)`, `.symbol(by:)` and
|
|
33
|
+
`.lineStyle(by:)`.
|
|
34
|
+
5. Configure axes with `.chartXAxis` and `.chartYAxis`.
|
|
35
|
+
6. Fix domains with `.chartXScale(domain:)` and `.chartYScale(domain:)`.
|
|
36
|
+
7. Add selection, scrolling and annotations where they help.
|
|
37
|
+
8. Above roughly 1,000 points in 2D, switch to vectorized plots (`BarPlot`,
|
|
38
|
+
`LinePlot` and friends).
|
|
74
39
|
|
|
75
|
-
|
|
40
|
+
Reviewing a chart: work down the checklist that closes this file.
|
|
76
41
|
|
|
77
|
-
|
|
42
|
+
## The `Chart` Container
|
|
78
43
|
|
|
79
44
|
```swift
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// Stacked by category (automatic when same x maps to multiple bars)
|
|
84
|
-
BarMark(x: .value("Month", item.month), y: .value("Sales", item.sales))
|
|
85
|
-
.foregroundStyle(by: .value("Product", item.product))
|
|
86
|
-
|
|
87
|
-
// Horizontal bar
|
|
88
|
-
BarMark(x: .value("Sales", item.sales), y: .value("Month", item.month))
|
|
89
|
-
|
|
90
|
-
// Interval bar (Gantt chart)
|
|
91
|
-
BarMark(
|
|
92
|
-
xStart: .value("Start", item.start),
|
|
93
|
-
xEnd: .value("End", item.end),
|
|
94
|
-
y: .value("Task", item.task)
|
|
95
|
-
)
|
|
96
|
-
```
|
|
45
|
+
import Charts
|
|
46
|
+
import SwiftUI
|
|
97
47
|
|
|
98
|
-
|
|
48
|
+
struct StepsChart: View {
|
|
49
|
+
let days: [DailySteps]
|
|
99
50
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.interpolationMethod(.catmullRom)
|
|
108
|
-
|
|
109
|
-
// Multi-series with explicit series parameter
|
|
110
|
-
LineMark(
|
|
111
|
-
x: .value("Date", item.date),
|
|
112
|
-
y: .value("Price", item.price),
|
|
113
|
-
series: .value("Ticker", item.ticker)
|
|
114
|
-
)
|
|
51
|
+
var body: some View {
|
|
52
|
+
Chart(days) { entry in
|
|
53
|
+
BarMark(x: .value("Date", entry.date, unit: .day),
|
|
54
|
+
y: .value("Steps", entry.count))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
115
58
|
```
|
|
116
59
|
|
|
117
|
-
|
|
60
|
+
- `Chart(data) { item in ... }` suits a single series.
|
|
61
|
+
- `Chart { ForEach(...) { ... }; RuleMark(...) }` mixes marks and series.
|
|
62
|
+
- `Chart(data, id: \.code) { ... }` uses a custom identifier.
|
|
63
|
+
- Every value is wrapped as `.value("Label", value)`, a `PlottableValue`.
|
|
118
64
|
|
|
119
|
-
|
|
120
|
-
PointMark(x: .value("Height", item.height), y: .value("Weight", item.weight))
|
|
121
|
-
.foregroundStyle(by: .value("Species", item.species))
|
|
122
|
-
.symbol(by: .value("Species", item.species))
|
|
123
|
-
.symbolSize(100)
|
|
124
|
-
```
|
|
65
|
+
## Marks
|
|
125
66
|
|
|
126
|
-
|
|
67
|
+
All of these are iOS 16 unless noted.
|
|
127
68
|
|
|
128
69
|
```swift
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
x: .value("Date", item.date),
|
|
136
|
-
yStart: .value("Min", item.min),
|
|
137
|
-
yEnd: .value("Max", item.max)
|
|
138
|
-
)
|
|
139
|
-
.opacity(0.3)
|
|
70
|
+
Chart {
|
|
71
|
+
ForEach(sales) { sale in
|
|
72
|
+
BarMark(x: .value("Store", sale.store), y: .value("Units", sale.units))
|
|
73
|
+
.foregroundStyle(by: .value("Channel", sale.channel))
|
|
74
|
+
}
|
|
75
|
+
}
|
|
140
76
|
```
|
|
141
77
|
|
|
142
|
-
|
|
78
|
+
- **`BarMark`**: vertical with a category on x and a value on y; swap x and y
|
|
79
|
+
for horizontal bars. Several bars on the same x with `.foregroundStyle(by:)`
|
|
80
|
+
stack automatically. `BarMark(xStart:xEnd:y:)` draws an interval, the
|
|
81
|
+
building block of a Gantt chart.
|
|
82
|
+
- **`LineMark`**: separate lines with `.foregroundStyle(by:)` or the
|
|
83
|
+
`series:` parameter; smooth with `.interpolationMethod(.catmullRom)`.
|
|
84
|
+
- **`PointMark`**: combine with `.foregroundStyle(by:)`, `.symbol(by:)` and
|
|
85
|
+
`.symbolSize(100)`.
|
|
86
|
+
- **`AreaMark`**: stacks with `.foregroundStyle(by:)`;
|
|
87
|
+
`AreaMark(x:yStart:yEnd:)` draws a band, usually with `.opacity(0.3)`.
|
|
88
|
+
- **`RuleMark`**: a threshold line.
|
|
143
89
|
|
|
144
90
|
```swift
|
|
145
|
-
RuleMark(y: .value("
|
|
146
|
-
.
|
|
147
|
-
.lineStyle(StrokeStyle(dash: [5, 3]))
|
|
91
|
+
RuleMark(y: .value("Goal", 10_000))
|
|
92
|
+
.lineStyle(StrokeStyle(lineWidth: 1.5, dash: [6, 4]))
|
|
148
93
|
.annotation(position: .top, alignment: .leading) {
|
|
149
|
-
Text("
|
|
94
|
+
Text("Daily goal").font(.caption)
|
|
150
95
|
}
|
|
151
96
|
```
|
|
152
97
|
|
|
153
|
-
|
|
98
|
+
- **`RectangleMark(x:y:)`** with `.foregroundStyle(by:)`: the cells of a heat
|
|
99
|
+
map.
|
|
100
|
+
- **`SectorMark`** (iOS 17): the slices of pies and donuts. Every value has
|
|
101
|
+
to be above zero; drop, combine or footnote any zero or negative entries
|
|
102
|
+
before they reach the chart.
|
|
154
103
|
|
|
155
104
|
```swift
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// Pie chart
|
|
164
|
-
Chart(data, id: \.name) { item in
|
|
165
|
-
SectorMark(angle: .value("Sales", item.sales))
|
|
166
|
-
.foregroundStyle(by: .value("Category", item.name))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Donut chart
|
|
170
|
-
Chart(data, id: \.name) { item in
|
|
171
|
-
SectorMark(
|
|
172
|
-
angle: .value("Sales", item.sales),
|
|
173
|
-
innerRadius: .ratio(0.618),
|
|
174
|
-
outerRadius: .inset(10),
|
|
175
|
-
angularInset: 1
|
|
176
|
-
)
|
|
177
|
-
.cornerRadius(4)
|
|
178
|
-
.foregroundStyle(by: .value("Category", item.name))
|
|
105
|
+
Chart(budget) { item in
|
|
106
|
+
SectorMark(angle: .value("Amount", item.amount),
|
|
107
|
+
innerRadius: .ratio(0.618),
|
|
108
|
+
outerRadius: .inset(10),
|
|
109
|
+
angularInset: 1)
|
|
110
|
+
.cornerRadius(4)
|
|
111
|
+
.foregroundStyle(by: .value("Envelope", item.envelope))
|
|
179
112
|
}
|
|
180
113
|
```
|
|
181
114
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
```swift
|
|
185
|
-
// Hide axes
|
|
186
|
-
.chartXAxis(.hidden)
|
|
187
|
-
.chartYAxis(.hidden)
|
|
115
|
+
Drop `innerRadius` and `angularInset` for a plain pie:
|
|
116
|
+
`SectorMark(angle:)` plus `.foregroundStyle(by:)`.
|
|
188
117
|
|
|
189
|
-
|
|
190
|
-
.chartXAxis {
|
|
191
|
-
AxisMarks(values: .stride(by: .month)) { value in
|
|
192
|
-
AxisGridLine()
|
|
193
|
-
AxisTick()
|
|
194
|
-
AxisValueLabel(format: .dateTime.month(.abbreviated))
|
|
195
|
-
}
|
|
196
|
-
}
|
|
118
|
+
## Axes
|
|
197
119
|
|
|
198
|
-
|
|
120
|
+
```swift
|
|
199
121
|
.chartXAxis {
|
|
200
122
|
AxisMarks(values: .stride(by: .day)) { _ in AxisGridLine() }
|
|
201
|
-
AxisMarks(values: .stride(by: .
|
|
123
|
+
AxisMarks(values: .stride(by: .weekOfYear)) { _ in
|
|
202
124
|
AxisTick()
|
|
203
125
|
AxisValueLabel(format: .dateTime.week())
|
|
204
126
|
}
|
|
205
127
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
.chartXAxisLabel("Time", position: .bottom, alignment: .center)
|
|
209
|
-
.chartYAxisLabel("Revenue ($)", position: .leading, alignment: .center)
|
|
128
|
+
.chartYAxis(.hidden)
|
|
129
|
+
.chartXAxisLabel("Date", position: .bottom, alignment: .center)
|
|
210
130
|
```
|
|
211
131
|
|
|
212
|
-
|
|
132
|
+
- `.chartXAxis(.hidden)` and `.chartYAxis(.hidden)` remove an axis.
|
|
133
|
+
- A single `AxisMarks(values: .stride(by: .month))` with `AxisGridLine()`,
|
|
134
|
+
`AxisTick()` and `AxisValueLabel(format: .dateTime.month(.abbreviated))` is
|
|
135
|
+
the common monthly axis.
|
|
136
|
+
- Several `AxisMarks` in one builder give grid lines and labels different
|
|
137
|
+
intervals, as above.
|
|
138
|
+
- Titles: `.chartXAxisLabel(_:position:alignment:)` and
|
|
139
|
+
`.chartYAxisLabel("Steps", position: .leading, alignment: .center)`.
|
|
140
|
+
|
|
141
|
+
## Scales
|
|
213
142
|
|
|
214
143
|
```swift
|
|
215
|
-
.chartYScale(domain: 0...100)
|
|
216
|
-
.chartYScale(domain: .automatic(includesZero: true))
|
|
217
|
-
.chartYScale(domain: 1...
|
|
218
|
-
.chartXScale(domain: ["
|
|
144
|
+
.chartYScale(domain: 0...100)
|
|
145
|
+
.chartYScale(domain: .automatic(includesZero: true))
|
|
146
|
+
.chartYScale(domain: 1...10_000, type: .log)
|
|
147
|
+
.chartXScale(domain: ["Small", "Medium", "Large", "XL"])
|
|
219
148
|
```
|
|
220
149
|
|
|
221
|
-
|
|
150
|
+
A numeric range fixes the domain, `.automatic(includesZero: true)` keeps zero
|
|
151
|
+
in view, `type: .log` gives a log scale, and an array of categories sets their
|
|
152
|
+
order.
|
|
153
|
+
|
|
154
|
+
## Colour and Encoding
|
|
222
155
|
|
|
223
156
|
```swift
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
)
|
|
157
|
+
.foregroundStyle(.teal)
|
|
158
|
+
.foregroundStyle(by: .value("Region", item.region))
|
|
159
|
+
.foregroundStyle(.linearGradient(colors: [.teal, .blue],
|
|
160
|
+
startPoint: .bottom, endPoint: .top))
|
|
229
161
|
```
|
|
230
162
|
|
|
231
|
-
|
|
163
|
+
A fixed style, a style driven by data, and a gradient.
|
|
164
|
+
|
|
165
|
+
## Selection (iOS 17)
|
|
232
166
|
|
|
233
167
|
```swift
|
|
234
|
-
@State private var
|
|
235
|
-
@State private var
|
|
236
|
-
@State private var
|
|
168
|
+
@State private var pickedDay: Date?
|
|
169
|
+
@State private var pickedWeek: ClosedRange<Date>?
|
|
170
|
+
@State private var pickedAngle: Double?
|
|
237
171
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
LineMark(x: .value("Date", item.date), y: .value("Value", item.value))
|
|
241
|
-
}
|
|
242
|
-
.chartXSelection(value: $selectedDate)
|
|
172
|
+
Chart(days) { BarMark(x: .value("Date", $0.date, unit: .day), y: .value("Steps", $0.count)) }
|
|
173
|
+
.chartXSelection(value: $pickedDay)
|
|
243
174
|
|
|
244
|
-
|
|
245
|
-
.chartXSelection(range: $
|
|
175
|
+
Chart(days) { BarMark(x: .value("Date", $0.date, unit: .day), y: .value("Steps", $0.count)) }
|
|
176
|
+
.chartXSelection(range: $pickedWeek)
|
|
246
177
|
|
|
247
|
-
|
|
248
|
-
.chartAngleSelection(value: $
|
|
178
|
+
Chart(budget) { SectorMark(angle: .value("Amount", $0.amount)) }
|
|
179
|
+
.chartAngleSelection(value: $pickedAngle)
|
|
249
180
|
```
|
|
250
181
|
|
|
251
|
-
|
|
182
|
+
`chartAngleSelection` hands back a position along the cumulative angle value,
|
|
183
|
+
not a category. Walk the sectors and add up their values to find which one
|
|
184
|
+
contains it; the patterns file has a full example.
|
|
185
|
+
|
|
186
|
+
## Scrolling (iOS 17)
|
|
252
187
|
|
|
253
188
|
```swift
|
|
254
|
-
Chart(
|
|
255
|
-
|
|
189
|
+
Chart(readings) { reading in
|
|
190
|
+
LineMark(x: .value("Time", reading.date, unit: .day),
|
|
191
|
+
y: .value("Level", reading.level))
|
|
256
192
|
}
|
|
257
193
|
.chartScrollableAxes(.horizontal)
|
|
258
|
-
.chartXVisibleDomain(length: 3600 * 24 * 7)
|
|
259
|
-
.chartScrollPosition(initialX:
|
|
194
|
+
.chartXVisibleDomain(length: 3600 * 24 * 7)
|
|
195
|
+
.chartScrollPosition(initialX: newestDate)
|
|
260
196
|
.chartScrollTargetBehavior(
|
|
261
|
-
.valueAligned(matching: DateComponents(hour: 0),
|
|
262
|
-
)
|
|
197
|
+
.valueAligned(matching: DateComponents(hour: 0),
|
|
198
|
+
majorAlignment: .page))
|
|
263
199
|
```
|
|
264
200
|
|
|
201
|
+
For a date axis the visible length is in seconds; this shows one week.
|
|
202
|
+
`valueAligned` snaps to midnight and pages by the visible width. Bucket dates
|
|
203
|
+
with `unit:` as in `.value("Time", reading.date, unit: .day)`.
|
|
204
|
+
|
|
265
205
|
## Annotations
|
|
266
206
|
|
|
267
207
|
```swift
|
|
268
|
-
BarMark(x: .value("
|
|
269
|
-
.annotation(position: .top, alignment: .center, spacing:
|
|
270
|
-
Text(
|
|
208
|
+
BarMark(x: .value("Quarter", row.quarter), y: .value("Orders", row.orders))
|
|
209
|
+
.annotation(position: .top, alignment: .center, spacing: 6) {
|
|
210
|
+
Text(row.orders, format: .number.notation(.compactName))
|
|
271
211
|
}
|
|
272
|
-
|
|
273
|
-
// Overflow resolution
|
|
274
|
-
.annotation(
|
|
275
|
-
position: .top,
|
|
276
|
-
overflowResolution: .init(x: .fit(to: .chart), y: .padScale)
|
|
277
|
-
) { Text("Label") }
|
|
278
212
|
```
|
|
279
213
|
|
|
214
|
+
When annotations near the edge get cut off:
|
|
215
|
+
`.annotation(position: .top, overflowResolution: .init(x: .fit(to: .chart), y: .disabled))`,
|
|
216
|
+
or `y: .padScale` to grow the scale so the annotation fits.
|
|
217
|
+
|
|
280
218
|
## Legend
|
|
281
219
|
|
|
282
220
|
```swift
|
|
283
|
-
.chartLegend(.hidden)
|
|
284
|
-
.chartLegend(position: .
|
|
285
|
-
.chartLegend(position: .bottom) {
|
|
286
|
-
HStack {
|
|
287
|
-
ForEach(categories, id: \.self) { cat in
|
|
288
|
-
Label(cat, systemImage: "circle.fill").font(.caption)
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
221
|
+
.chartLegend(.hidden)
|
|
222
|
+
.chartLegend(position: .top, alignment: .leading, spacing: 8)
|
|
223
|
+
.chartLegend(position: .bottom) { RegionLegend(regions: regions) }
|
|
292
224
|
```
|
|
293
225
|
|
|
294
|
-
## Vectorized Plots (iOS 18
|
|
226
|
+
## Vectorized Plots (iOS 18)
|
|
295
227
|
|
|
296
|
-
|
|
228
|
+
For about 1,000 points or more. They take a whole collection, or a function.
|
|
297
229
|
|
|
298
230
|
```swift
|
|
299
|
-
// Data-driven
|
|
300
231
|
Chart {
|
|
301
|
-
BarPlot(
|
|
302
|
-
.foregroundStyle(\.
|
|
232
|
+
BarPlot(hourly, x: .value("Hour", \.hour), y: .value("Requests", \.requests))
|
|
233
|
+
.foregroundStyle(\.tint)
|
|
234
|
+
.opacity(0.9)
|
|
303
235
|
}
|
|
304
236
|
|
|
305
|
-
// Function plotting: y = f(x)
|
|
306
237
|
Chart {
|
|
307
|
-
LinePlot(x: "
|
|
238
|
+
LinePlot(x: "Input", y: "Output", domain: -3...3) { x in x * x * x - 4 * x }
|
|
308
239
|
}
|
|
309
240
|
|
|
310
|
-
// Parametric: (x, y) = f(t)
|
|
311
241
|
Chart {
|
|
312
|
-
LinePlot(x: "
|
|
313
|
-
(x: cos(
|
|
242
|
+
LinePlot(x: "East", y: "North", t: "Phase", domain: 0...(2 * .pi)) { phase in
|
|
243
|
+
(x: cos(3 * phase), y: sin(2 * phase))
|
|
314
244
|
}
|
|
315
245
|
}
|
|
316
246
|
```
|
|
317
247
|
|
|
318
|
-
|
|
248
|
+
Modifiers that take a key path must come before modifiers that take a plain
|
|
249
|
+
value; the other order does not compile.
|
|
319
250
|
|
|
320
|
-
|
|
321
|
-
BarPlot(data, x: .value("X", \.x), y: .value("Y", \.y))
|
|
322
|
-
.foregroundStyle(\.color) // KeyPath first
|
|
323
|
-
.opacity(0.8) // Value modifier second
|
|
324
|
-
```
|
|
251
|
+
## 3D Charts (iOS 26)
|
|
325
252
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
accepts `SurfacePlot` plus 3D initializers of `PointMark`, `RuleMark`, and
|
|
331
|
-
`RectangleMark`.
|
|
253
|
+
Use `Chart3D` for data with three real spatial dimensions or a surface of two
|
|
254
|
+
variables. Do not use it to decorate ordinary category or time-series data.
|
|
255
|
+
`Chart3D` accepts `SurfacePlot` and the 3D initialisers of `PointMark`,
|
|
256
|
+
`RuleMark` and `RectangleMark`.
|
|
332
257
|
|
|
333
258
|
```swift
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
259
|
+
struct TerrainChart: View {
|
|
260
|
+
@State private var viewAngle: Chart3DPose = .default
|
|
261
|
+
|
|
262
|
+
var body: some View {
|
|
263
|
+
Chart3D {
|
|
264
|
+
SurfacePlot(x: "Longitude", y: "Elevation", z: "Latitude") { x, z in
|
|
265
|
+
sin(x) * cos(z)
|
|
266
|
+
}
|
|
267
|
+
.foregroundStyle(.heightBased)
|
|
268
|
+
}
|
|
269
|
+
.chartXScale(domain: -3...3)
|
|
270
|
+
.chartYScale(domain: -1...1)
|
|
271
|
+
.chartZScale(domain: -3...3)
|
|
272
|
+
.chart3DPose($viewAngle)
|
|
339
273
|
}
|
|
340
|
-
.foregroundStyle(.heightBased)
|
|
341
274
|
}
|
|
342
|
-
.chartXScale(domain: -2...2)
|
|
343
|
-
.chartYScale(domain: -1...1)
|
|
344
|
-
.chartZScale(domain: -2...2)
|
|
345
|
-
.chart3DPose($pose)
|
|
346
275
|
```
|
|
347
276
|
|
|
348
277
|
## Common Mistakes
|
|
349
278
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
Chart {
|
|
362
|
-
ForEach(allCities) { item in
|
|
363
|
-
LineMark(x: .value("Date", item.date), y: .value("Temp", item.temp))
|
|
364
|
-
.foregroundStyle(by: .value("City", item.city))
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### 2. Too many SectorMark slices
|
|
370
|
-
|
|
371
|
-
```swift
|
|
372
|
-
// WRONG -- 20 tiny sectors are unreadable
|
|
373
|
-
Chart(twentyCategories, id: \.name) { item in
|
|
374
|
-
SectorMark(angle: .value("Value", item.value))
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// CORRECT -- group into top 5 + "Other"
|
|
378
|
-
Chart(groupedData, id: \.name) { item in
|
|
379
|
-
SectorMark(angle: .value("Value", item.value))
|
|
380
|
-
.foregroundStyle(by: .value("Category", item.name))
|
|
381
|
-
}
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### 3. Missing scale domain when zero-baseline matters
|
|
385
|
-
|
|
386
|
-
```swift
|
|
387
|
-
// WRONG -- axis starts at ~95; small changes look dramatic
|
|
388
|
-
Chart(data) {
|
|
389
|
-
LineMark(x: .value("Day", $0.day), y: .value("Score", $0.score))
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// CORRECT -- explicit domain for honest representation
|
|
393
|
-
Chart(data) {
|
|
394
|
-
LineMark(x: .value("Day", $0.day), y: .value("Score", $0.score))
|
|
395
|
-
}
|
|
396
|
-
.chartYScale(domain: 0...100)
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
### 4. Static foregroundStyle overriding data encoding
|
|
400
|
-
|
|
401
|
-
```swift
|
|
402
|
-
// WRONG -- static color overrides by-value encoding
|
|
403
|
-
BarMark(x: .value("X", item.x), y: .value("Y", item.y))
|
|
404
|
-
.foregroundStyle(by: .value("Category", item.category))
|
|
405
|
-
.foregroundStyle(.blue)
|
|
406
|
-
|
|
407
|
-
// CORRECT -- use only the data encoding
|
|
408
|
-
BarMark(x: .value("X", item.x), y: .value("Y", item.y))
|
|
409
|
-
.foregroundStyle(by: .value("Category", item.category))
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### 5. Individual marks for 10,000+ data points
|
|
413
|
-
|
|
414
|
-
```swift
|
|
415
|
-
// WRONG -- creates 10,000 mark views; slow
|
|
416
|
-
Chart(largeDataset) { item in
|
|
417
|
-
PointMark(x: .value("X", item.x), y: .value("Y", item.y))
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
// CORRECT -- vectorized plot (iOS 18+)
|
|
421
|
-
Chart {
|
|
422
|
-
PointPlot(largeDataset, x: .value("X", \.x), y: .value("Y", \.y))
|
|
423
|
-
}
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
### 6. Fixed chart height breaking Dynamic Type
|
|
427
|
-
|
|
428
|
-
```swift
|
|
429
|
-
// WRONG -- clips axis labels at large text sizes
|
|
430
|
-
Chart(data) { ... }
|
|
431
|
-
.frame(height: 200)
|
|
432
|
-
|
|
433
|
-
// CORRECT -- adaptive sizing
|
|
434
|
-
Chart(data) { ... }
|
|
435
|
-
.frame(minHeight: 200, maxHeight: 400)
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### 7. KeyPath modifier after value modifier on vectorized plots
|
|
439
|
-
|
|
440
|
-
```swift
|
|
441
|
-
// WRONG -- compiler error
|
|
442
|
-
BarPlot(data, x: .value("X", \.x), y: .value("Y", \.y))
|
|
443
|
-
.opacity(0.8)
|
|
444
|
-
.foregroundStyle(\.color)
|
|
445
|
-
|
|
446
|
-
// CORRECT -- KeyPath modifiers first
|
|
447
|
-
BarPlot(data, x: .value("X", \.x), y: .value("Y", \.y))
|
|
448
|
-
.foregroundStyle(\.color)
|
|
449
|
-
.opacity(0.8)
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
### 8. Missing accessibility labels
|
|
453
|
-
|
|
454
|
-
```swift
|
|
455
|
-
// WRONG -- VoiceOver users get no context
|
|
456
|
-
Chart(data) {
|
|
457
|
-
BarMark(x: .value("Month", $0.month), y: .value("Sales", $0.sales))
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// CORRECT -- add per-mark accessibility
|
|
461
|
-
Chart(data) { item in
|
|
462
|
-
BarMark(x: .value("Month", item.month), y: .value("Sales", item.sales))
|
|
463
|
-
.accessibilityLabel("\(item.month)")
|
|
464
|
-
.accessibilityValue("\(item.sales) units sold")
|
|
465
|
-
}
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### 9. Treating angle selection as category selection
|
|
469
|
-
|
|
470
|
-
`chartAngleSelection(value:)` binds the selected plottable angle value. For
|
|
471
|
-
pie and donut charts, map that numeric value through cumulative sector ranges
|
|
472
|
-
before comparing it to a category label.
|
|
279
|
+
| Mistake | Fix |
|
|
280
|
+
|---------|-----|
|
|
281
|
+
| Several series drawn as one zig-zag line | Add `.foregroundStyle(by:)` or `series:` |
|
|
282
|
+
| A pie with 20 slices | Keep the top five and group the rest as "Other" |
|
|
283
|
+
| No explicit domain where the zero baseline matters, so small changes look huge | `.chartYScale(domain: 0...100)` or `includesZero` |
|
|
284
|
+
| `.foregroundStyle(.blue)` after `.foregroundStyle(by:)` | The fixed style overrides the encoding; keep only the encoding |
|
|
285
|
+
| 10,000 individual marks | `PointPlot` and the other vectorized plots (iOS 18) |
|
|
286
|
+
| `.frame(height: 200)` clipping axis labels at large Dynamic Type sizes | `.frame(minHeight: 200, maxHeight: 400)` |
|
|
287
|
+
| A plain-value modifier before a key-path modifier on a vectorized plot | Put key-path modifiers first |
|
|
288
|
+
| No accessibility on marks | `.accessibilityLabel` and `.accessibilityValue` per mark |
|
|
289
|
+
| Comparing the `chartAngleSelection` value with a category name | Map the angle through cumulative sector ranges first |
|
|
473
290
|
|
|
474
291
|
## Review Checklist
|
|
475
292
|
|
|
476
|
-
- [ ] Data
|
|
477
|
-
- [ ]
|
|
478
|
-
- [ ] Multi-series lines use `series:`
|
|
479
|
-
- [ ] Axes
|
|
480
|
-
- [ ]
|
|
481
|
-
- [ ]
|
|
482
|
-
- [ ] Selection
|
|
483
|
-
- [ ]
|
|
484
|
-
- [ ] Scrollable charts set `.chartXVisibleDomain(length:)`
|
|
485
|
-
- [ ] Vectorized plots
|
|
486
|
-
- [ ]
|
|
487
|
-
- [ ]
|
|
488
|
-
- [ ]
|
|
489
|
-
- [ ] Chart
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
-
|
|
496
|
-
-
|
|
497
|
-
-
|
|
498
|
-
- Apple docs: [Swift Charts updates](https://sosumi.ai/documentation/updates/swiftcharts)
|
|
499
|
-
- Apple docs: [Chart3D](https://sosumi.ai/documentation/charts/Chart3D)
|
|
500
|
-
- Apple docs: [SurfacePlot](https://sosumi.ai/documentation/charts/SurfacePlot)
|
|
293
|
+
- [ ] Data is `Identifiable` or has an `id:` key path
|
|
294
|
+
- [ ] The mark suits the question: bars compare, lines show trends, sectors show shares
|
|
295
|
+
- [ ] Multi-series lines use `series:` or `.foregroundStyle(by:)`
|
|
296
|
+
- [ ] Axes have suitable labels, ticks and grid lines
|
|
297
|
+
- [ ] An explicit domain where the zero baseline matters
|
|
298
|
+
- [ ] Pies and donuts: positive values, five to seven slices, an "Other" group
|
|
299
|
+
- [ ] Selection bindings match the axis type (`Date?` for a date axis)
|
|
300
|
+
- [ ] Angle selection is mapped back to a category
|
|
301
|
+
- [ ] Scrollable charts set `.chartXVisibleDomain(length:)`
|
|
302
|
+
- [ ] Vectorized plots for more than about 1,000 points, key-path modifiers first
|
|
303
|
+
- [ ] `Chart3D` reserved for genuine spatial data or surfaces; z domain and pose reviewed
|
|
304
|
+
- [ ] Marks carry accessibility labels; checked at large text sizes and in Dark Mode
|
|
305
|
+
- [ ] The legend is visible and placed, or hidden on purpose
|
|
306
|
+
- [ ] Chart data types are `Sendable`, and chart data is updated on the main actor
|
|
307
|
+
|
|
308
|
+
## Apple Documentation
|
|
309
|
+
|
|
310
|
+
- [Swift Charts](https://developer.apple.com/documentation/charts)
|
|
311
|
+
- [Building a first chart](https://developer.apple.com/documentation/charts/creating-a-chart-using-swift-charts)
|
|
312
|
+
- [Swift Charts updates](https://developer.apple.com/documentation/updates/swiftcharts)
|
|
313
|
+
- [Chart3D](https://developer.apple.com/documentation/charts/chart3d)
|
|
314
|
+
- [SurfacePlot](https://developer.apple.com/documentation/charts/surfaceplot)
|