@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.
Files changed (264) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +266 -267
  5. package/package.json +2 -2
  6. package/pipeline/scripts/_notices.mjs +1 -1
  7. package/pipeline/skills/.skill-manifest.json +68 -68
  8. package/pipeline/skills/shared/README.md +70 -70
  9. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  10. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  11. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  12. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  13. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  14. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  15. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  16. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  17. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  18. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  19. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  20. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
  21. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  22. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
  23. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
  24. package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
  25. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  26. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  27. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  28. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
  29. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  30. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  31. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  32. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  34. package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
  35. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  36. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
  37. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  38. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  39. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  40. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  41. package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
  42. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  43. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
  44. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  45. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  46. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  47. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  48. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  49. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  50. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  51. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  52. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  53. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
  54. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  55. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  56. package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
  57. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  58. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  59. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  60. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  61. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  62. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  63. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  64. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  65. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  66. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  67. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  68. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  69. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  70. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  71. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  72. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  73. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  74. package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
  75. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  76. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  77. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  78. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  79. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  80. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  81. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  82. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  83. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  84. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  85. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  86. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  87. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  88. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  89. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  90. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  91. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  92. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  93. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  94. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  95. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  96. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  97. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  98. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  99. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  100. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  101. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  102. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  103. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  104. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  105. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  106. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  107. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  108. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  109. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  111. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
  112. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  113. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  114. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  115. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  116. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  117. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  118. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  119. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  120. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  121. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  122. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  123. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  124. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  125. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  126. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  127. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  128. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  129. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  130. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  131. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  132. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  133. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  134. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  135. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  136. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  137. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  138. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  139. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  140. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  141. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  142. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  143. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  144. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  145. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  146. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  147. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  148. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  149. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  150. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  151. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  152. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  153. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  154. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  155. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  156. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  157. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
  158. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  159. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  160. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  161. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  162. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  163. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  164. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  165. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  166. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  167. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  168. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  169. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  170. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  171. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  172. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
  173. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  174. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  175. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  176. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  177. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  178. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  179. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  180. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  181. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  182. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  183. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  184. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  185. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  186. package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
  187. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  188. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  189. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
  190. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  191. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  192. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  193. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  194. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  195. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  196. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
  197. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  198. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  199. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  200. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
  201. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  202. package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
  203. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  204. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
  205. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  206. package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
  207. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  208. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  209. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  210. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  211. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  212. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  213. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  214. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  215. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  216. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  217. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  218. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  219. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  220. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  221. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  222. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  223. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  224. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  225. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  226. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  227. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  228. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  229. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  230. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  231. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
  232. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  233. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
  234. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  235. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
  236. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  237. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  238. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  239. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  240. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  241. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  242. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  243. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  244. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  245. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  246. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  247. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  248. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  249. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  250. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  251. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  252. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  253. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  254. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  255. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  256. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  257. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  258. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  259. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  260. package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
  261. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  262. package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
  263. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
  264. package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
@@ -1,423 +1,334 @@
1
1
  ---
2
2
  name: core-motion
3
- description: "Access Core Motion accelerometer, gyroscope, magnetometer, device-motion, pedometer, activity-recognition, altitude, headphone motion, batched high-frequency workout motion, and water-submersion/depth data. Use when reading device sensors, counting steps, detecting walking/running/driving/cycling, tracking altitude, building motion interactions, handling AirPods head tracking, or implementing watchOS dive/depth features."
3
+ description: "Core Motion on iOS and watchOS: accelerometer, gyroscope, magnetometer, fused device motion and reference frames, CMPedometer steps, distance and floors, activity recognition, barometric and absolute altitude, AirPods head tracking, batched high-rate workout capture, watchOS water submersion and depth. Use when building tilt controls, step counters, activity-aware features, altitude tracking or other motion interactions."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # CoreMotion
8
+ # Core Motion
9
9
 
10
- Read device sensor data -- accelerometer, gyroscope, magnetometer, pedometer,
11
- activity recognition, altitude, headphone motion, batched motion, and submersion
12
- depth -- on iOS and watchOS. CoreMotion fuses raw sensor inputs into processed
13
- device-motion data and provides pedometer/activity APIs for fitness and
14
- navigation use cases. Targets Swift 6.3 / iOS 26+.
10
+ Core Motion turns the accelerometer, gyroscope, magnetometer and barometer into
11
+ data an app can act on. It fuses the raw sensors into a single device-motion
12
+ stream and also ships higher-level services: a pedometer, an activity
13
+ classifier and an altimeter. Fitness, navigation, games and accessibility
14
+ features all build on it. Examples assume Swift 6.3 and iOS 26 or later.
15
15
 
16
- ## Contents
16
+ Longer SwiftUI services, batched sensors, head tracking, a step dashboard,
17
+ activity-driven modes and dive support live in the
18
+ [motion patterns reference](references/motion-patterns.md).
17
19
 
18
- - [Setup](#setup)
19
- - [CMMotionManager: Sensor Data](#cmmotionmanager-sensor-data)
20
- - [Processed Device Motion](#processed-device-motion)
21
- - [CMPedometer: Step and Distance Data](#cmpedometer-step-and-distance-data)
22
- - [CMMotionActivityManager: Activity Recognition](#cmmotionactivitymanager-activity-recognition)
23
- - [CMAltimeter: Altitude Data](#cmaltimeter-altitude-data)
24
- - [Update Intervals and Battery](#update-intervals-and-battery)
25
- - [Common Mistakes](#common-mistakes)
26
- - [Review Checklist](#review-checklist)
27
- - [References](#references)
20
+ Covers: activity recognition (walking, running, driving, cycling) and
21
+ distance and floor counts from `CMPedometer`. Not for HealthKit workout
22
+ sessions or SensorKit research data.
28
23
 
29
24
  ## Setup
30
25
 
31
- ### Info.plist
26
+ ### Usage string
32
27
 
33
- Add `NSMotionUsageDescription` to Info.plist with a user-facing string explaining
34
- why your app needs motion data. Without this key, the app crashes on first access.
35
-
36
- ```xml
37
- <key>NSMotionUsageDescription</key>
38
- <string>This app uses motion data to track your activity.</string>
39
- ```
28
+ Info.plist must carry `NSMotionUsageDescription`, a sentence telling the user
29
+ why the app reads motion. If the key is absent, the process is terminated the first
30
+ time it touches a protected motion API.
40
31
 
41
32
  ### Authorization
42
33
 
43
- Use the matching manager's `authorizationStatus()` or `authorizationStatus`
44
- property when an API exposes one (`CMPedometer`, `CMMotionActivityManager`,
45
- `CMAltimeter`, headphone motion, batched sensors, and submersion). Raw
46
- `CMMotionManager` accelerometer/gyro/device-motion streams have no explicit
47
- authorization request API; still ship the usage string and handle errors from
48
- start/update callbacks.
34
+ Several managers expose an authorization status: `CMPedometer`,
35
+ `CMMotionActivityManager`, `CMAltimeter`, `CMHeadphoneMotionManager`,
36
+ `CMBatchedSensorManager` and `CMWaterSubmersionManager`. Read it before you
37
+ start updates. The raw `CMMotionManager` streams (accelerometer, gyroscope,
38
+ device motion) have no request call at all; ship the usage string anyway and
39
+ treat errors delivered to the handler as the failure signal.
49
40
 
50
41
  ```swift
51
42
  import CoreMotion
52
43
 
53
- let status = CMMotionActivityManager.authorizationStatus()
54
- switch status {
55
- case .notDetermined:
56
- // Will prompt on first use
57
- break
58
- case .authorized:
59
- break
60
- case .restricted, .denied:
61
- // Direct user to Settings
62
- break
63
- @unknown default:
64
- break
44
+ enum MotionAccess {
45
+ case ready, willPrompt, blocked
65
46
  }
66
- ```
67
-
68
- ## CMMotionManager: Sensor Data
69
-
70
- Create exactly **one** `CMMotionManager` per app. Multiple instances degrade
71
- sensor update rates.
72
47
 
73
- ```swift
74
- import CoreMotion
75
-
76
- let motionManager = CMMotionManager()
48
+ func pedometerAccess() -> MotionAccess {
49
+ switch CMPedometer.authorizationStatus() {
50
+ case .authorized: return .ready
51
+ case .notDetermined: return .willPrompt // system asks on first query
52
+ case .denied, .restricted: return .blocked // point the user at Settings
53
+ @unknown default: return .blocked
54
+ }
55
+ }
77
56
  ```
78
57
 
79
- ### Accelerometer Updates
58
+ ## CMMotionManager: raw sensors
80
59
 
81
- ```swift
82
- guard motionManager.isAccelerometerAvailable else { return }
60
+ Create one `CMMotionManager` for the whole app. Extra instances compete for
61
+ the same hardware and every one of them receives updates at a lower rate.
83
62
 
84
- motionManager.accelerometerUpdateInterval = 1.0 / 60.0 // 60 Hz
63
+ ### Accelerometer
85
64
 
86
- motionManager.startAccelerometerUpdates(to: .main) { data, error in
87
- guard let acceleration = data?.acceleration else { return }
88
- print("x: \(acceleration.x), y: \(acceleration.y), z: \(acceleration.z)")
65
+ ```swift
66
+ @MainActor let sensors = CMMotionManager()
67
+
68
+ @MainActor func beginShakeDetection(onShake: @escaping () -> Void) {
69
+ guard sensors.isAccelerometerAvailable else { return }
70
+ sensors.accelerometerUpdateInterval = 1.0 / 60.0
71
+ sensors.startAccelerometerUpdates(to: .main) { sample, error in
72
+ guard let a = sample?.acceleration, error == nil else { return }
73
+ let magnitude = (a.x * a.x + a.y * a.y + a.z * a.z).squareRoot()
74
+ if magnitude > 2.5 { onShake() }
75
+ }
89
76
  }
90
77
 
91
- // When done:
92
- motionManager.stopAccelerometerUpdates()
78
+ @MainActor func endShakeDetection() { sensors.stopAccelerometerUpdates() }
93
79
  ```
94
80
 
95
- ### Gyroscope Updates
81
+ `CMMotionManager` is not `Sendable`, so Swift 6 rejects a plain global `let` of
82
+ it ("not concurrency-safe"). The shared instance is therefore `@MainActor`, and
83
+ so is every function that touches it; the same goes for the pedometer,
84
+ activity and altimeter globals below. Handlers queued on `.main` run on the
85
+ main thread either way.
96
86
 
97
- ```swift
98
- guard motionManager.isGyroAvailable else { return }
99
-
100
- motionManager.gyroUpdateInterval = 1.0 / 60.0
87
+ ### Gyroscope
101
88
 
102
- motionManager.startGyroUpdates(to: .main) { data, error in
103
- guard let rotationRate = data?.rotationRate else { return }
104
- print("x: \(rotationRate.x), y: \(rotationRate.y), z: \(rotationRate.z)")
89
+ ```swift
90
+ @MainActor func beginSpinTracking() {
91
+ guard sensors.isGyroAvailable else { return }
92
+ sensors.gyroUpdateInterval = 1.0 / 30.0
93
+ sensors.startGyroUpdates(to: .main) { sample, error in
94
+ guard let spin = sample?.rotationRate, error == nil else { return }
95
+ _ = spin.z // radians per second around each axis
96
+ }
105
97
  }
106
98
 
107
- motionManager.stopGyroUpdates()
99
+ @MainActor func endSpinTracking() { sensors.stopGyroUpdates() }
108
100
  ```
109
101
 
110
- ### Polling Pattern (Games)
102
+ ### Polling from a game loop
111
103
 
112
- For games, start updates without a handler and poll the latest sample each frame:
104
+ A game that already runs a per-frame loop can skip the handler. Call the
105
+ start method with no arguments and read the latest value when drawing.
113
106
 
114
107
  ```swift
115
- motionManager.startAccelerometerUpdates()
108
+ sensors.startAccelerometerUpdates()
116
109
 
117
- // In your game loop / display link:
118
- if let data = motionManager.accelerometerData {
119
- let tilt = data.acceleration.x
120
- // Move player based on tilt
110
+ @MainActor func tick() { // called from a display link or render loop
111
+ guard let latest = sensors.accelerometerData else { return }
112
+ applyTilt(x: latest.acceleration.x)
121
113
  }
122
114
  ```
123
115
 
124
- ## Processed Device Motion
116
+ ## Device motion
125
117
 
126
- Device motion fuses accelerometer, gyroscope, and magnetometer into a single
127
- `CMDeviceMotion` object with attitude, user acceleration (gravity removed),
128
- rotation rate, and calibrated magnetic field.
118
+ `CMDeviceMotion` blends accelerometer, gyroscope and magnetometer readings.
119
+ Each sample carries `attitude`, `userAcceleration` (gravity already removed),
120
+ `gravity`, `rotationRate`, a calibrated `magneticField` and `heading`, which is
121
+ reported in degrees relative to the active reference frame.
129
122
 
130
- When giving device-motion guidance, show the runtime frame check in the snippet
131
- instead of hard-coding a corrected, magnetic-north, or true-north frame. Fall
132
- back to `.xArbitraryZVertical` when the preferred frame is unavailable.
123
+ Never hard-code a reference frame. Ask
124
+ `CMMotionManager.availableAttitudeReferenceFrames()` at runtime and fall back
125
+ to `.xArbitraryZVertical`.
133
126
 
134
127
  ```swift
135
- guard motionManager.isDeviceMotionAvailable else { return }
136
-
137
- let availableFrames = CMMotionManager.availableAttitudeReferenceFrames()
138
- let frame: CMAttitudeReferenceFrame = availableFrames.contains(.xArbitraryCorrectedZVertical)
139
- ? .xArbitraryCorrectedZVertical
140
- : .xArbitraryZVertical
141
-
142
- motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
143
-
144
- motionManager.startDeviceMotionUpdates(
145
- using: frame,
146
- to: .main
147
- ) { motion, error in
148
- guard let motion else { return }
149
-
150
- let attitude = motion.attitude // roll, pitch, yaw
151
- let userAccel = motion.userAcceleration
152
- let gravity = motion.gravity
153
- let heading = motion.heading // degrees relative to the current frame
154
-
155
- print("Pitch: \(attitude.pitch), Roll: \(attitude.roll)")
128
+ @MainActor func beginOrientationTracking() {
129
+ guard sensors.isDeviceMotionAvailable else { return }
130
+ let offered = CMMotionManager.availableAttitudeReferenceFrames()
131
+ let frame: CMAttitudeReferenceFrame =
132
+ offered.contains(.xArbitraryCorrectedZVertical)
133
+ ? .xArbitraryCorrectedZVertical
134
+ : .xArbitraryZVertical
135
+
136
+ sensors.deviceMotionUpdateInterval = 1.0 / 30.0
137
+ sensors.startDeviceMotionUpdates(using: frame, to: .main) { reading, failure in
138
+ guard let reading, failure == nil else { return }
139
+ let tilt = reading.attitude // roll, pitch, yaw in radians
140
+ let push = reading.userAcceleration // in g, gravity removed
141
+ let down = reading.gravity
142
+ let degrees = reading.heading
143
+ _ = (tilt.roll, push.z, down.y, degrees)
144
+ }
156
145
  }
157
146
 
158
- motionManager.stopDeviceMotionUpdates()
147
+ @MainActor func endOrientationTracking() { sensors.stopDeviceMotionUpdates() }
159
148
  ```
160
149
 
161
- ### Attitude Reference Frames
150
+ ### Reference frames
162
151
 
163
- For simple tilt controls, use `.xArbitraryZVertical` or
164
- `.xArbitraryCorrectedZVertical`; they avoid magnetometer/location dependencies.
165
- Before requesting corrected, magnetic-north, or true-north frames, call
166
- `CMMotionManager.availableAttitudeReferenceFrames()` and fall back to an
167
- available frame.
152
+ | Frame | X axis | Needs | Good for |
153
+ |---|---|---|---|
154
+ | `.xArbitraryZVertical` | wherever the device pointed at start; the default | nothing extra | most games, tilt |
155
+ | `.xArbitraryCorrectedZVertical` | same, with gyro drift corrected over time | nothing extra | longer tilt sessions |
156
+ | `.xMagneticNorthZVertical` | magnetic north | magnetometer | compass-like UI |
157
+ | `.xTrueNorthZVertical` | true north | magnetometer and location | geographic alignment |
168
158
 
169
- | Frame | Use Case |
170
- |---|---|
171
- | `.xArbitraryZVertical` | Default. Z is vertical, X arbitrary at start. Most games. |
172
- | `.xArbitraryCorrectedZVertical` | Same as above, corrected for gyro drift over time. |
173
- | `.xMagneticNorthZVertical` | X points to magnetic north. Requires magnetometer. |
174
- | `.xTrueNorthZVertical` | X points to true north. Requires magnetometer + location. |
159
+ For plain tilt, pick one of the two arbitrary frames: they do not depend on the
160
+ magnetometer or on location. Before asking for a north frame, confirm
161
+ `availableAttitudeReferenceFrames().contains(...)` includes it.
175
162
 
176
- Check available frames before use:
163
+ ## CMPedometer
177
164
 
178
- ```swift
179
- let available = CMMotionManager.availableAttitudeReferenceFrames()
180
- if available.contains(.xTrueNorthZVertical) {
181
- // Safe to use true north
182
- }
183
- ```
184
-
185
- ## CMPedometer: Step and Distance Data
186
-
187
- `CMPedometer` provides step counts, distance, pace, cadence, and floor counts.
165
+ The pedometer reports step count, distance, pace, cadence and floors climbed
166
+ or descended.
188
167
 
189
168
  ```swift
190
- let pedometer = CMPedometer()
191
-
192
- guard CMPedometer.isStepCountingAvailable() else { return }
193
-
194
- // Historical query
195
- pedometer.queryPedometerData(
196
- from: Calendar.current.startOfDay(for: Date()),
197
- to: Date()
198
- ) { data, error in
199
- guard let data else { return }
200
- print("Steps today: \(data.numberOfSteps)")
201
- print("Distance: \(data.distance?.doubleValue ?? 0) meters")
202
- print("Floors up: \(data.floorsAscended?.intValue ?? 0)")
169
+ @MainActor let stepCounter = CMPedometer()
170
+
171
+ @MainActor func loadTodaysWalk() {
172
+ guard CMPedometer.isStepCountingAvailable() else { return }
173
+ let midnight = Calendar.current.startOfDay(for: .now)
174
+ stepCounter.queryPedometerData(from: midnight, to: .now) { summary, error in
175
+ guard let summary, error == nil else { return }
176
+ let steps = summary.numberOfSteps.intValue
177
+ let meters = summary.distance?.doubleValue ?? 0
178
+ let climbed = summary.floorsAscended?.intValue ?? 0
179
+ _ = (steps, meters, climbed)
180
+ }
203
181
  }
204
182
 
205
- // Live updates
206
- pedometer.startUpdates(from: Date()) { data, error in
207
- guard let data else { return }
208
- print("Steps: \(data.numberOfSteps)")
183
+ @MainActor func followLiveSteps(since start: Date) {
184
+ stepCounter.startUpdates(from: start) { summary, _ in
185
+ _ = summary?.numberOfSteps
186
+ }
209
187
  }
210
188
 
211
- // Stop when done
212
- pedometer.stopUpdates()
189
+ @MainActor func stopLiveSteps() { stepCounter.stopUpdates() }
213
190
  ```
214
191
 
215
- ### Availability Checks
192
+ Each metric has its own capability check:
216
193
 
217
- | Method | What It Checks |
218
- |---|---|
219
- | `isStepCountingAvailable()` | Step counter hardware |
220
- | `isDistanceAvailable()` | Distance estimation |
221
- | `isFloorCountingAvailable()` | Barometric altimeter for floors |
222
- | `isPaceAvailable()` | Pace data |
223
- | `isCadenceAvailable()` | Cadence data |
194
+ - `isStepCountingAvailable()` - step hardware present
195
+ - `isDistanceAvailable()` - distance estimates
196
+ - `isFloorCountingAvailable()` - floors, which need a barometer
197
+ - `isPaceAvailable()` - pace
198
+ - `isCadenceAvailable()` - cadence
224
199
 
225
- ## CMMotionActivityManager: Activity Recognition
200
+ ## CMMotionActivityManager
226
201
 
227
- Detects whether the user is stationary, walking, running, cycling, or in a vehicle.
202
+ The classifier reports stationary, walking, running, cycling and automotive
203
+ states.
228
204
 
229
205
  ```swift
230
- let activityManager = CMMotionActivityManager()
231
-
232
- guard CMMotionActivityManager.isActivityAvailable() else { return }
233
-
234
- // Live activity updates
235
- activityManager.startActivityUpdates(to: .main) { activity in
236
- guard let activity else { return }
237
-
238
- if activity.walking {
239
- print("Walking (confidence: \(activity.confidence.rawValue))")
240
- } else if activity.running {
241
- print("Running")
242
- } else if activity.automotive {
243
- print("In vehicle")
244
- } else if activity.cycling {
245
- print("Cycling")
246
- } else if activity.stationary {
247
- print("Stationary")
206
+ @MainActor let classifier = CMMotionActivityManager()
207
+
208
+ @MainActor func watchMovement() {
209
+ guard CMMotionActivityManager.isActivityAvailable() else { return }
210
+ classifier.startActivityUpdates(to: .main) { activity in
211
+ guard let activity else { return }
212
+ let flags = (activity.walking, activity.running, activity.cycling,
213
+ activity.automotive, activity.stationary)
214
+ let certainty = activity.confidence.rawValue // 0 low, 1 medium, 2 high
215
+ _ = (flags, certainty)
248
216
  }
249
217
  }
250
218
 
251
- activityManager.stopActivityUpdates()
219
+ @MainActor func stopWatchingMovement() { classifier.stopActivityUpdates() }
252
220
  ```
253
221
 
254
- ### Historical Activity Query
222
+ ### Looking back
255
223
 
256
224
  ```swift
257
- let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
258
-
259
- activityManager.queryActivityStarting(
260
- from: yesterday,
261
- to: Date(),
262
- to: .main
263
- ) { activities, error in
264
- guard let activities else { return }
265
- for activity in activities {
266
- print("\(activity.startDate): walking=\(activity.walking)")
225
+ @MainActor func lastDayOfActivity() {
226
+ let end = Date.now
227
+ let start = end.addingTimeInterval(-24 * 60 * 60)
228
+ classifier.queryActivityStarting(from: start, to: end, to: .main) { entries, _ in
229
+ for entry in entries ?? [] { _ = entry.startDate }
267
230
  }
268
231
  }
269
232
  ```
270
233
 
271
- ## CMAltimeter: Altitude Data
272
-
273
- Altimeter access is covered by `NSMotionUsageDescription`; handle denied motion
274
- access through unavailable data and update-handler errors.
234
+ ## CMAltimeter
275
235
 
276
- ```swift
277
- let altimeter = CMAltimeter()
236
+ The same `NSMotionUsageDescription` covers the altimeter. When the user denies
237
+ motion access, altitude simply stops being available and the handlers receive
238
+ errors.
278
239
 
279
- guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
280
-
281
- altimeter.startRelativeAltitudeUpdates(to: .main) { data, error in
282
- guard let data else { return }
283
- print("Relative altitude: \(data.relativeAltitude) meters")
284
- print("Pressure: \(data.pressure) kPa")
285
- }
286
-
287
- altimeter.stopRelativeAltitudeUpdates()
288
- ```
289
-
290
- Absolute altitude is altitude relative to sea level, not GPS-based altitude.
291
- First check availability. Absolute altitude is available only on supported
292
- hardware such as iPhone 12 or later and Apple Watch Series 6, Apple Watch SE, or
293
- later.
240
+ ### Relative altitude
294
241
 
295
242
  ```swift
296
- guard CMAltimeter.isAbsoluteAltitudeAvailable() else { return }
297
-
298
- altimeter.startAbsoluteAltitudeUpdates(to: .main) { data, error in
299
- guard let data else { return }
300
- print("Altitude: \(data.altitude)m, accuracy: \(data.accuracy)m")
243
+ @MainActor let barometer = CMAltimeter()
244
+
245
+ @MainActor func trackClimb() {
246
+ guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
247
+ barometer.startRelativeAltitudeUpdates(to: .main) { reading, error in
248
+ guard let reading, error == nil else { return }
249
+ let gainedMeters = reading.relativeAltitude.doubleValue
250
+ let kilopascals = reading.pressure.doubleValue
251
+ _ = (gainedMeters, kilopascals)
252
+ }
301
253
  }
302
254
 
303
- altimeter.stopAbsoluteAltitudeUpdates()
255
+ @MainActor func stopClimb() { barometer.stopRelativeAltitudeUpdates() }
304
256
  ```
305
257
 
306
- ## Update Intervals and Battery
307
-
308
- | Interval | Hz | Use Case | Battery Impact |
309
- |---|---|---|---|
310
- | `1.0 / 10.0` | 10 | UI orientation | Low |
311
- | `1.0 / 30.0` | 30 | Casual games | Moderate |
312
- | `1.0 / 60.0` | 60 | Action games | High |
313
- | `1.0 / 100.0` | 100 | Max rate (iPhone) | Very High |
314
-
315
- Use the lowest frequency that meets your needs. Do not assume a fixed maximum
316
- sample rate across devices. For high-frequency workout motion, use
317
- `CMBatchedSensorManager` where supported and read its reported
318
- `accelerometerDataFrequency` or `deviceMotionDataFrequency` instead of assigning
319
- those read-only properties.
258
+ ### Absolute altitude
320
259
 
321
- ## Common Mistakes
322
-
323
- ### DON'T: Create multiple CMMotionManager instances
324
-
325
- ```swift
326
- // WRONG -- degrades update rates for all instances
327
- class ViewA { let motion = CMMotionManager() }
328
- class ViewB { let motion = CMMotionManager() }
329
-
330
- // CORRECT -- single instance, shared across the app
331
- @Observable
332
- final class MotionService {
333
- static let shared = MotionService()
334
- let manager = CMMotionManager()
335
- }
336
- ```
337
-
338
- ### DON'T: Skip sensor availability checks
260
+ Absolute altitude is height above sea level estimated by the system, not a GPS
261
+ fix. Supported hardware starts at iPhone 12 on the phone side; on the wrist it
262
+ starts at Apple Watch Series 6 and Apple Watch SE. Always gate on `isAbsoluteAltitudeAvailable()`.
339
263
 
340
264
  ```swift
341
- // WRONG -- crashes on devices without gyroscope
342
- motionManager.startGyroUpdates(to: .main) { data, _ in }
343
-
344
- // CORRECT -- check first
345
- guard motionManager.isGyroAvailable else {
346
- showUnsupportedMessage()
347
- return
348
- }
349
- motionManager.startGyroUpdates(to: .main) { data, _ in }
350
- ```
351
-
352
- ### DON'T: Forget to stop updates
353
-
354
- ```swift
355
- // WRONG -- updates keep running, draining battery
356
- class MotionVC: UIViewController {
357
- override func viewDidAppear(_ animated: Bool) {
358
- super.viewDidAppear(animated)
359
- motionManager.startAccelerometerUpdates(to: .main) { _, _ in }
265
+ @MainActor func trackElevation() {
266
+ guard CMAltimeter.isAbsoluteAltitudeAvailable() else { return }
267
+ barometer.startAbsoluteAltitudeUpdates(to: .main) { reading, error in
268
+ guard let reading, error == nil else { return }
269
+ _ = (reading.altitude, reading.accuracy) // both in meters
360
270
  }
361
- // Missing viewDidDisappear stop!
362
271
  }
363
272
 
364
- // CORRECT -- stop in the counterpart lifecycle method
365
- override func viewDidDisappear(_ animated: Bool) {
366
- super.viewDidDisappear(animated)
367
- motionManager.stopAccelerometerUpdates()
368
- }
369
- ```
370
-
371
- ### DON'T: Use unnecessarily high update rates
372
-
373
- ```swift
374
- // WRONG -- 100 Hz for a compass display
375
- motionManager.deviceMotionUpdateInterval = 1.0 / 100.0
376
-
377
- // CORRECT -- 10 Hz is more than enough for a compass
378
- motionManager.deviceMotionUpdateInterval = 1.0 / 10.0
379
- ```
380
-
381
- ### DON'T: Assume all CMMotionActivity properties are mutually exclusive
382
-
383
- ```swift
384
- // WRONG -- checking only one property
385
- if activity.walking { handleWalking() }
386
-
387
- // CORRECT -- multiple can be true simultaneously; check confidence
388
- if activity.walking && activity.confidence == .high {
389
- handleWalking()
390
- } else if activity.automotive && activity.confidence != .low {
391
- handleDriving()
392
- }
273
+ @MainActor func stopElevation() { barometer.stopAbsoluteAltitudeUpdates() }
393
274
  ```
394
275
 
395
- ## Review Checklist
276
+ ## Update rates and battery
396
277
 
397
- - [ ] `NSMotionUsageDescription` present in Info.plist with a clear explanation
398
- - [ ] Single `CMMotionManager` instance shared across the app
399
- - [ ] Sensor availability checked before starting updates (`isAccelerometerAvailable`, etc.)
400
- - [ ] Authorization status checked before pedometer/activity APIs
401
- - [ ] Update interval set to the lowest acceptable frequency
402
- - [ ] All `start*Updates` calls have matching `stop*Updates` in lifecycle counterparts
403
- - [ ] Handlers dispatched to appropriate queues (not blocking main for heavy processing)
404
- - [ ] `CMMotionActivity.confidence` checked before acting on activity type
405
- - [ ] Error parameters checked in update handlers
406
- - [ ] Device-motion snippets call `CMMotionManager.availableAttitudeReferenceFrames()` before requesting a specific attitude frame
407
- - [ ] Attitude reference frame chosen based on actual need (not defaulting to true north unnecessarily)
278
+ | Use case | Frequency | Energy impact | Interval to set |
279
+ |---|---|---|---|
280
+ | UI that follows orientation | 10 Hz | low | `1.0 / 10.0` |
281
+ | Casual game | 30 Hz | moderate | `1.0 / 30.0` |
282
+ | Fast action game | 60 Hz | high | `1.0 / 60.0` |
283
+ | Fastest iPhone sampling | 100 Hz | very high | `1.0 / 100.0` |
284
+
285
+ Pick the slowest rate the feature tolerates. The ceiling differs from one
286
+ device model to the next, so no code path should rely on a fixed maximum. For high-frequency workout
287
+ analysis, prefer `CMBatchedSensorManager` where it is supported, and read its
288
+ `accelerometerDataFrequency` or `deviceMotionDataFrequency`. Those two
289
+ properties are read-only; there is nothing to assign.
290
+
291
+ ## Common mistakes
292
+
293
+ - **Several `CMMotionManager` objects.** Rates drop for all of them. Wrap one
294
+ manager in a shared `@Observable` service exposed as `static let shared`.
295
+ - **No availability guard.** Starting gyroscope updates without checking
296
+ `isGyroAvailable` can crash on hardware that lacks one. Guard first and tell
297
+ the user the feature is unsupported.
298
+ - **Never stopping.** Sensors keep running and drain the battery. Pair every
299
+ start with a stop in the matching lifecycle callback, for example
300
+ `viewDidAppear` with `viewDidDisappear`.
301
+ - **Oversampling.** A compass needle does not need 100 Hz; 10 Hz is plenty.
302
+ - **Treating activity flags as exclusive.** Several can be true together.
303
+ Combine them with `confidence`, for example act on `walking` only at `.high`,
304
+ and on `automotive` only when confidence is not `.low`.
305
+
306
+ ## Review checklist
307
+
308
+ - [ ] Info.plist has a clear `NSMotionUsageDescription`
309
+ - [ ] The app owns exactly one shared `CMMotionManager`
310
+ - [ ] Availability (`isAccelerometerAvailable` and friends) is checked before any start call
311
+ - [ ] Authorization is read before pedometer and activity APIs are used
312
+ - [ ] The update interval is the lowest that still works
313
+ - [ ] Every `start*Updates` has a `stop*Updates` in the opposite lifecycle event
314
+ - [ ] Handlers run on a suitable queue and heavy processing stays off the main thread
315
+ - [ ] `CMMotionActivity.confidence` is checked before the app reacts
316
+ - [ ] Handler `error` parameters are inspected
317
+ - [ ] Device-motion code calls `availableAttitudeReferenceFrames()` before choosing a frame
318
+ - [ ] The frame matches the need; true north is never the default
408
319
 
409
320
  ## References
410
321
 
411
- - Extended patterns (SwiftUI integration, batched sensor manager, headphone motion, water submersion): [references/motion-patterns.md](references/motion-patterns.md)
412
- - [CoreMotion framework](https://sosumi.ai/documentation/coremotion)
413
- - [CMMotionManager](https://sosumi.ai/documentation/coremotion/cmmotionmanager)
414
- - [CMPedometer](https://sosumi.ai/documentation/coremotion/cmpedometer)
415
- - [CMMotionActivityManager](https://sosumi.ai/documentation/coremotion/cmmotionactivitymanager)
416
- - [CMDeviceMotion](https://sosumi.ai/documentation/coremotion/cmdevicemotion)
417
- - [CMAltimeter](https://sosumi.ai/documentation/coremotion/cmaltimeter)
418
- - [CMAbsoluteAltitudeData](https://sosumi.ai/documentation/coremotion/cmabsolutealtitudedata)
419
- - [CMBatchedSensorManager](https://sosumi.ai/documentation/coremotion/cmbatchedsensormanager)
420
- - [CMHeadphoneMotionManager](https://sosumi.ai/documentation/coremotion/cmheadphonemotionmanager)
421
- - [CMWaterSubmersionManager](https://sosumi.ai/documentation/coremotion/cmwatersubmersionmanager)
422
- - [Accessing submersion data](https://sosumi.ai/documentation/coremotion/accessing-submersion-data)
423
- - [Getting processed device-motion data](https://sosumi.ai/documentation/coremotion/getting-processed-device-motion-data)
322
+ - [Motion patterns](references/motion-patterns.md) - SwiftUI services, batched sensors, headphone motion, pedometer dashboard, activity modes, water submersion
323
+ - [Core Motion](https://developer.apple.com/documentation/coremotion)
324
+ - [CMMotionManager](https://developer.apple.com/documentation/coremotion/cmmotionmanager)
325
+ - [CMPedometer](https://developer.apple.com/documentation/coremotion/cmpedometer)
326
+ - [CMMotionActivityManager](https://developer.apple.com/documentation/coremotion/cmmotionactivitymanager)
327
+ - [CMDeviceMotion](https://developer.apple.com/documentation/coremotion/cmdevicemotion)
328
+ - [CMAltimeter](https://developer.apple.com/documentation/coremotion/cmaltimeter)
329
+ - [CMAbsoluteAltitudeData](https://developer.apple.com/documentation/coremotion/cmabsolutealtitudedata)
330
+ - [CMBatchedSensorManager](https://developer.apple.com/documentation/coremotion/cmbatchedsensormanager)
331
+ - [CMHeadphoneMotionManager](https://developer.apple.com/documentation/coremotion/cmheadphonemotionmanager)
332
+ - [CMWaterSubmersionManager](https://developer.apple.com/documentation/coremotion/cmwatersubmersionmanager)
333
+ - [Accessing submersion data](https://developer.apple.com/documentation/coremotion/accessing-submersion-data)
334
+ - [Getting processed device-motion data](https://developer.apple.com/documentation/coremotion/getting-processed-device-motion-data)