@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,87 +1,109 @@
1
1
  ---
2
2
  name: mapkit-location
3
- description: "Implement, review, or improve maps and location features in iOS/macOS apps using MapKit and CoreLocation. Use when working with Map views, annotations, markers, polylines, user location tracking, geocoding, reverse geocoding, search/autocomplete, directions and routes, geofencing, region monitoring, CLLocationUpdate async streams, or location authorization flows. Also use when working with maps, coordinates, addresses, places, directions, distance calculations, or location-based features in Swift apps."
3
+ description: "MapKit and CoreLocation on iOS and macOS: SwiftUI Map, markers, annotations, polylines and overlays, camera control, user location tracking, CLLocationUpdate streams, location authorization, geocoding and reverse geocoding, search and autocomplete, directions, routes and ETA, CLMonitor geofencing and region monitoring, background location, distance math. Use when implementing, reviewing or improving anything built on maps, coordinates, addresses, places, directions or distances."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
7
 
8
- # MapKit
8
+ # MapKit and CoreLocation
9
9
 
10
- Build map-based and location-aware features targeting iOS 17+ with SwiftUI
11
- MapKit and modern CoreLocation async APIs. Use `Map` with `MapContentBuilder`
12
- for views, `CLLocationUpdate.liveUpdates()` for streaming location, and
13
- `CLMonitor` for geofencing.
10
+ Two frameworks do the work here. MapKit draws the map and answers questions
11
+ about places (search, geocoding, routes). CoreLocation tells you where the
12
+ device is and when it crosses a boundary. Since iOS 17 both have a Swift-first
13
+ surface: a SwiftUI `Map` whose content is written in a `MapContentBuilder`
14
+ closure, the async sequence `CLLocationUpdate.liveUpdates()` for position, and
15
+ the `CLMonitor` actor for geofences. Write new code against those; reach for
16
+ `MKMapView` or `CLLocationManager` only for the gaps named below.
14
17
 
15
- Read [references/mapkit-patterns.md](references/mapkit-patterns.md) when you need full map setup, search,
16
- routes, Look Around, snapshots, or iOS 26 place APIs. Read
17
- [references/mapkit-corelocation-patterns.md](references/mapkit-corelocation-patterns.md) when the task involves
18
- location update lifecycle, geofencing, background location, testing, or privacy keys.
18
+ Baseline: iOS 17. Sections that need a later release say so, and code that
19
+ needs it carries `@available`.
19
20
 
20
- ## Contents
21
+ Longer material lives in two references:
21
22
 
22
- - [Workflow](#workflow)
23
- - [SwiftUI Map View (iOS 17+)](#swiftui-map-view-ios-17)
24
- - [CoreLocation Modern API](#corelocation-modern-api)
25
- - [Geocoding](#geocoding)
26
- - [Search](#search)
27
- - [Directions](#directions)
28
- - [PlaceDescriptor (iOS 26+)](#placedescriptor-ios-26)
29
- - [Common Mistakes](#common-mistakes)
30
- - [Review Checklist](#review-checklist)
31
- - [References](#references)
23
+ - [Map patterns](references/mapkit-patterns.md): a complete
24
+ map screen, custom annotations, camera control, search with autocomplete,
25
+ routes, Look Around, snapshots, dense annotations, iOS 26 place APIs,
26
+ coordinate helpers, accessibility.
27
+ - [Location patterns](references/mapkit-corelocation-patterns.md):
28
+ the location update lifecycle, diagnostics, `CLServiceSession`, `CLMonitor`
29
+ geofencing, background location, legacy `CLLocationManager` cases, accuracy,
30
+ simulator testing, Info.plist privacy keys.
32
31
 
33
- ## Workflow
32
+ ## Scope
34
33
 
35
- ### 1. Add a map with markers or annotations
34
+ In scope: maps, markers and annotations, overlays, routes, search and
35
+ geocoding, the user's position, `CLMonitor` geofencing and the rules for
36
+ location in the background.
36
37
 
37
- 1. Import `MapKit`.
38
- 2. Create a `Map` view with optional `MapCameraPosition` binding.
39
- 3. Add `Marker`, `Annotation`, `MapPolyline`, `MapPolygon`, or `MapCircle`
40
- inside the `MapContentBuilder` closure.
41
- 4. Configure map style with `.mapStyle()`.
42
- 5. Add map controls with `.mapControls { }`.
43
- 6. Handle selection with a `selection:` binding.
38
+ Neighbouring work belongs elsewhere. MapKit does not draw CarPlay templates,
39
+ launch App Clips or pair Bluetooth hardware, so never claim it does. What this
40
+ skill owns is the handoff point: a geofence event, a search result or a route
41
+ that the other framework then acts on.
44
42
 
45
- ### 2. Track user location
43
+ | Topic | Where it goes |
44
+ |-------|---------------|
45
+ | CarPlay map templates, navigation alerts, CarPlay UI | CarPlay framework guidance (no skill in this collection) |
46
+ | App Clip invocation from a place card, size limits, handoff to the full app | `app-clips` |
47
+ | Pairing a beacon or accessory when a geofence fires | `core-bluetooth`, or AccessorySetupKit |
48
+ | A Live Activity used to keep background location alive | `live-activities` |
46
49
 
47
- 1. Add `NSLocationWhenInUseUsageDescription` to Info.plist.
48
- 2. On iOS 18+, create a `CLServiceSession` to manage authorization.
49
- 3. Iterate `CLLocationUpdate.liveUpdates()` in a `Task`.
50
- 4. Filter updates by distance or accuracy before updating the UI.
51
- 5. Stop the task when location tracking is no longer needed.
50
+ ## Workflows
52
51
 
53
- ### 3. Search for places
52
+ ### 1. Put places on a map
54
53
 
55
- 1. Configure `MKLocalSearchCompleter` for autocomplete suggestions.
56
- 2. Debounce user input (at least 300ms) before setting the query.
57
- 3. Convert selected completion to `MKLocalSearch.Request` for full results.
58
- 4. Display results as markers or in a list.
54
+ 1. `import MapKit` (and `SwiftUI`).
55
+ 2. Create a `Map`. Bind a `MapCameraPosition` if code needs to move the camera.
56
+ 3. Inside the content closure add `Marker`, `Annotation`, `MapPolyline`,
57
+ `MapPolygon` or `MapCircle`.
58
+ 4. Pick a look with `.mapStyle(...)`.
59
+ 5. Add controls with `.mapControls { ... }`.
60
+ 6. For tap-to-select, pass a `selection:` binding.
59
61
 
60
- ### 4. Get directions and display a route
62
+ ### 2. Follow the user's position
61
63
 
62
- 1. Create an `MKDirections.Request` with source and destination `MKMapItem`.
63
- 2. Set `transportType` (`.automobile`, `.walking`, `.transit`, `.cycling`).
64
- 3. Await `MKDirections.calculate()`.
65
- 4. Draw the route with `MapPolyline(route.polyline)`.
64
+ 1. Put a `NSLocationWhenInUseUsageDescription` string in Info.plist.
65
+ 2. On iOS 18 and later, create a `CLServiceSession` when the feature starts
66
+ and keep it until the feature ends; it drives the authorization prompt.
67
+ 3. Iterate `CLLocationUpdate.liveUpdates()` inside a `Task` that you keep.
68
+ 4. Drop samples that are inaccurate, old or implausible before the UI sees them.
69
+ 5. Cancel the task as soon as the feature no longer needs position.
66
70
 
67
- ### 5. Review existing map/location code
71
+ ### 3. Find places
68
72
 
69
- Run through the Review Checklist at the end of this file.
73
+ 1. Feed typed text to an `MKLocalSearchCompleter` for suggestions.
74
+ 2. Wait at least 300 ms after the last keystroke before updating the query.
75
+ 3. Turn the picked suggestion into an `MKLocalSearch.Request` for full results.
76
+ 4. Show the `MKMapItem` results as markers, a list, or both.
70
77
 
71
- ## SwiftUI Map View (iOS 17+)
78
+ ### 4. Route between two places
79
+
80
+ 1. Build an `MKDirections.Request` with a source and destination `MKMapItem`.
81
+ 2. Choose a mode in `transportType` (car, walking, transit or cycling).
82
+ 3. `try await MKDirections(request:).calculate()`.
83
+ 4. Draw `MapPolyline(route.polyline)`.
84
+
85
+ ### 5. Review existing code
86
+
87
+ Go through the [Review Checklist](#review-checklist) below.
88
+
89
+ ## SwiftUI Map (iOS 17+)
90
+
91
+ A SwiftUI map file imports both `SwiftUI` and `MapKit`.
72
92
 
73
93
  ```swift
74
- import MapKit
75
94
  import SwiftUI
95
+ import MapKit
76
96
 
77
- struct PlaceMap: View {
78
- @State private var position: MapCameraPosition = .automatic
97
+ struct TrailheadMap: View {
98
+ @State private var camera: MapCameraPosition = .automatic
99
+
100
+ private let lot = CLLocationCoordinate2D(latitude: 46.852, longitude: -121.760)
101
+ private let summit = CLLocationCoordinate2D(latitude: 46.853, longitude: -121.727)
79
102
 
80
103
  var body: some View {
81
- Map(position: $position) {
82
- Marker("Apple Park", coordinate: applePark)
83
- Marker("Infinite Loop", systemImage: "building.2",
84
- coordinate: infiniteLoop)
104
+ Map(position: $camera) {
105
+ Marker("Parking", coordinate: lot)
106
+ Marker("Summit", systemImage: "mountain.2.fill", coordinate: summit)
85
107
  }
86
108
  .mapStyle(.standard(elevation: .realistic))
87
109
  .mapControls {
@@ -93,173 +115,175 @@ struct PlaceMap: View {
93
115
  }
94
116
  ```
95
117
 
96
- ### Marker and Annotation
118
+ ### Marker or Annotation
97
119
 
98
- ```swift
99
- // Balloon marker -- simplest way to pin a location
100
- Marker("Cafe", systemImage: "cup.and.saucer.fill", coordinate: cafeCoord)
101
- .tint(.brown)
120
+ - `Marker(_:systemImage:coordinate:)` draws the system balloon. It is the
121
+ cheapest way to flag a spot, VoiceOver reads its title, and `.tint(_:)`
122
+ recolours it.
123
+ - `Annotation(_:coordinate:anchor:content:)` puts any SwiftUI view at a
124
+ coordinate. `anchor` is a `UnitPoint`; `.bottom` makes the bottom edge of
125
+ the view touch the coordinate, which suits pin-shaped content.
102
126
 
103
- // Annotation -- custom SwiftUI view at a coordinate
104
- Annotation("You", coordinate: userCoord, anchor: .bottom) {
105
- Image(systemName: "figure.wave")
127
+ ```swift
128
+ Annotation("Ranger station", coordinate: station, anchor: .bottom) {
129
+ Image(systemName: "house.fill")
106
130
  .padding(6)
107
- .background(.blue.gradient, in: .circle)
108
131
  .foregroundStyle(.white)
132
+ .background(Circle().fill(.green.gradient))
109
133
  }
110
134
  ```
111
135
 
112
- ### Overlays: Polyline, Polygon, Circle
136
+ ### Overlays
113
137
 
114
- ```swift
115
- Map {
116
- // Polyline from coordinates
117
- MapPolyline(coordinates: routeCoords)
118
- .stroke(.blue, lineWidth: 4)
119
-
120
- // Polygon (area highlight)
121
- MapPolygon(coordinates: parkBoundary)
122
- .foregroundStyle(.green.opacity(0.3))
123
- .stroke(.green, lineWidth: 2)
124
-
125
- // Circle (radius around a point)
126
- MapCircle(center: storeCoord, radius: 500)
127
- .foregroundStyle(.red.opacity(0.15))
128
- .stroke(.red, lineWidth: 1)
129
- }
130
- ```
138
+ | Content | Draws | Styling |
139
+ |---------|-------|---------|
140
+ | `MapPolyline(coordinates:)` | a line through the points | `.stroke(.orange, lineWidth: 4)` |
141
+ | `MapPolygon(coordinates:)` | a filled area | `.foregroundStyle(.teal.opacity(0.25))` plus `.stroke(...)` for the edge |
142
+ | `MapCircle(center:radius:)` | a circle, radius in metres | `.foregroundStyle(...)` and `.stroke(...)` |
131
143
 
132
- ### Camera Position
144
+ ### Camera position
133
145
 
134
- `MapCameraPosition` controls what the map displays. Bind it to let the user
135
- interact and to programmatically move the camera. Initialize it with `.region`,
136
- `.userLocation(fallback:)`, `.camera`, `.item`, `.rect`, or `.automatic`. See
137
- [references/mapkit-patterns.md](references/mapkit-patterns.md) ("Camera Control") for the position
138
- initializers, animated fly-to, framing content, and reading the visible region.
146
+ `MapCameraPosition` is what the map is showing. Bound to the map, it moves
147
+ when the user pans and moves the map when code assigns it. Its constructors:
148
+ `.region`, `.userLocation(fallback:)`, `.camera`, `.item`, `.rect`,
149
+ `.automatic`. Animated moves, framing all content and reading the visible
150
+ region are in [Camera Control](references/mapkit-patterns.md#camera-control).
139
151
 
140
- ### Map Style
152
+ ### Map styles
141
153
 
142
- ```swift
143
- .mapStyle(.standard) // Default road map
144
- .mapStyle(.standard(elevation: .realistic, showsTraffic: true))
145
- .mapStyle(.imagery) // Satellite
146
- .mapStyle(.imagery(elevation: .realistic)) // 3D satellite
147
- .mapStyle(.hybrid) // Satellite + labels
148
- .mapStyle(.hybrid(elevation: .realistic, showsTraffic: true))
149
- ```
154
+ | Modifier | Result |
155
+ |----------|--------|
156
+ | `.mapStyle(.standard)` | default road map |
157
+ | `.mapStyle(.standard(elevation: .realistic, showsTraffic: true))` | roads, 3D terrain, live traffic |
158
+ | `.mapStyle(.imagery)` | satellite |
159
+ | `.mapStyle(.imagery(elevation: .realistic))` | satellite in 3D |
160
+ | `.mapStyle(.hybrid)` | satellite with labels |
161
+ | `.mapStyle(.hybrid(elevation: .realistic, showsTraffic: true))` | labelled satellite, 3D terrain, live traffic |
150
162
 
151
- ### Map Interaction Modes
163
+ ### Interaction modes
152
164
 
153
- ```swift
154
- .mapInteractionModes(.all) // Default: pan, zoom, rotate, pitch
155
- .mapInteractionModes(.pan) // Pan only
156
- .mapInteractionModes([.pan, .zoom]) // Pan and zoom
157
- .mapInteractionModes([]) // Static map (no interaction)
158
- ```
165
+ | Modifier | Allows |
166
+ |----------|--------|
167
+ | `.mapInteractionModes(.all)` | pan, zoom, rotate, pitch (the default) |
168
+ | `.mapInteractionModes(.pan)` | panning only |
169
+ | `.mapInteractionModes([.pan, .zoom])` | moving and zooming, no rotation or tilt |
170
+ | `.mapInteractionModes([])` | nothing; a static picture |
171
+
172
+ ### Selection
159
173
 
160
- ### Map Selection
174
+ The value in `.tag(_:)` must have the same type as the `selection` binding,
175
+ or taps select nothing.
161
176
 
162
177
  ```swift
163
- @State private var selectedMarker: MKMapItem?
178
+ struct CampsiteMap: View {
179
+ let sites: [Campsite]
180
+ @State private var chosen: MKMapItem?
181
+ @State private var headline = ""
164
182
 
165
- Map(selection: $selectedMarker) {
166
- ForEach(places) { place in
167
- Marker(place.name, coordinate: place.coordinate)
168
- .tag(place.mapItem) // Tag must match selection type
183
+ var body: some View {
184
+ Map(selection: $chosen) {
185
+ ForEach(sites) { site in
186
+ Marker(site.name, coordinate: site.coordinate)
187
+ .tag(site.mapItem)
188
+ }
189
+ }
190
+ .onChange(of: chosen) { _, item in
191
+ guard let item else { return }
192
+ headline = item.name ?? ""
193
+ }
169
194
  }
170
195
  }
171
- .onChange(of: selectedMarker) { _, newValue in
172
- guard let item = newValue else { return }
173
- // React to selection
174
- }
175
196
  ```
176
197
 
177
- ## CoreLocation Modern API
198
+ ## CoreLocation
178
199
 
179
200
  ### CLLocationUpdate.liveUpdates() (iOS 17+)
180
201
 
181
- Replace `CLLocationManagerDelegate` callbacks with a single async sequence.
182
- Each iteration yields a `CLLocationUpdate` containing an optional `CLLocation`.
183
- On iOS 18+, handle diagnostic states such as denied authorization, globally
184
- disabled Location Services, unavailable location, and insufficient in-use
185
- conditions with a visible degraded path instead of silently waiting forever.
186
- Store the task so the feature can cancel it, and reject invalid, inaccurate,
187
- stale, or unusable movement data before driving map UI or background work.
202
+ One async sequence replaces the `CLLocationManagerDelegate` callbacks. Each
203
+ element is a `CLLocationUpdate` whose `location` is optional. Rules:
204
+
205
+ - Store the iterating `Task` in a property; cancelling it is how tracking stops.
206
+ - Throw away samples with invalid or poor accuracy, old timestamps or
207
+ impossible jumps before they touch map UI or background work.
208
+ - On iOS 18 and later the update also carries diagnostics (authorization
209
+ denied, Location Services off system-wide, location unavailable, app not
210
+ sufficiently in use). React with a visible fallback instead of waiting on a
211
+ sequence that will not deliver.
188
212
 
189
213
  ```swift
190
214
  import CoreLocation
215
+ import Observation
191
216
 
192
217
  @MainActor
193
218
  @Observable
194
- final class LocationTracker {
195
- var currentLocation: CLLocation?
196
- private var updateTask: Task<Void, Never>?
219
+ final class RunTracker {
220
+ private(set) var lastFix: CLLocation?
221
+ private var stream: Task<Void, Never>?
197
222
 
198
- func startTracking() {
199
- updateTask = Task {
223
+ func begin() {
224
+ stream?.cancel()
225
+ stream = Task {
200
226
  do {
201
- let updates = CLLocationUpdate.liveUpdates()
202
- for try await update in updates {
203
- guard let location = update.location else { continue }
204
- // Filter by horizontal accuracy
205
- guard location.horizontalAccuracy >= 0,
206
- location.horizontalAccuracy < 50 else { continue }
207
- currentLocation = location
227
+ for try await reading in CLLocationUpdate.liveUpdates() {
228
+ guard let fix = reading.location,
229
+ fix.horizontalAccuracy >= 0,
230
+ fix.horizontalAccuracy < 50 else { continue }
231
+ lastFix = fix
208
232
  }
209
233
  } catch is CancellationError {
210
- // Expected when tracking stops.
211
234
  } catch {
212
- currentLocation = nil
235
+ lastFix = nil
213
236
  }
214
237
  }
215
238
  }
216
239
 
217
- func stopTracking() {
218
- updateTask?.cancel()
219
- updateTask = nil
240
+ func end() {
241
+ stream?.cancel()
242
+ stream = nil
220
243
  }
221
244
  }
222
245
  ```
223
246
 
247
+ Diagnostics, the full filter set and a mapping from each state to UI are in
248
+ the [location reference](references/mapkit-corelocation-patterns.md#diagnostics-and-fallbacks-ios-18).
249
+
224
250
  ### CLServiceSession (iOS 18+)
225
251
 
226
- Declare authorization requirements for a feature's lifetime. Hold a reference
227
- to the session for as long as you need location services.
252
+ A `CLServiceSession` states what authorization a feature needs, for as long
253
+ as the feature runs. Store it in a property and release it when the feature
254
+ ends. On iOS 18 `liveUpdates()` and `CLMonitor` create a session implicitly
255
+ when you have not; create one yourself when you need `.always` or full
256
+ accuracy. It is not available on macOS.
228
257
 
229
258
  ```swift
230
- // When-in-use authorization with full accuracy preference
231
- let session = CLServiceSession(
259
+ @available(iOS 18, *)
260
+ let nearbySession = CLServiceSession(
232
261
  authorization: .whenInUse,
233
- fullAccuracyPurposeKey: "NearbySearchPurpose"
262
+ fullAccuracyPurposeKey: "NearbyTrails"
234
263
  )
235
- // Hold `session` as a stored property; release it when done.
236
264
  ```
237
265
 
238
- On iOS 18+, `CLLocationUpdate.liveUpdates()` and `CLMonitor` take an implicit
239
- `CLServiceSession` if you do not create one explicitly. Create one explicitly
240
- when you need `.always` authorization or full accuracy.
266
+ ### Authorization
241
267
 
242
- ### Authorization Flow
268
+ - `NSLocationWhenInUseUsageDescription` is required for any location use.
269
+ - `NSLocationAlwaysAndWhenInUseUsageDescription` only when the feature truly
270
+ needs `.always`.
243
271
 
244
- ```swift
245
- // Info.plist keys (required):
246
- // NSLocationWhenInUseUsageDescription
247
- // NSLocationAlwaysAndWhenInUseUsageDescription (only if .always needed)
272
+ A denied user should see why the feature is empty and a way out:
248
273
 
249
- // Check authorization and guide user to Settings when denied
250
- struct LocationPermissionView: View {
274
+ ```swift
275
+ struct LocationOffView: View {
251
276
  @Environment(\.openURL) private var openURL
252
277
 
253
278
  var body: some View {
254
279
  ContentUnavailableView {
255
- Label("Location Access Denied", systemImage: "location.slash")
280
+ Label("Location is off", systemImage: "location.slash")
256
281
  } description: {
257
- Text("Enable location access in Settings to use this feature.")
282
+ Text("Allow location access to see trails near you.")
258
283
  } actions: {
259
284
  Button("Open Settings") {
260
- if let url = URL(string: UIApplication.openSettingsURLString) {
261
- openURL(url)
262
- }
285
+ guard let settings = URL(string: UIApplication.openSettingsURLString) else { return }
286
+ openURL(settings)
263
287
  }
264
288
  }
265
289
  }
@@ -268,164 +292,168 @@ struct LocationPermissionView: View {
268
292
 
269
293
  ## Geocoding
270
294
 
271
- ### CLGeocoder (iOS 8+)
295
+ ### MKGeocodingRequest and MKReverseGeocodingRequest (iOS 26+)
296
+
297
+ MapKit now geocodes by itself and returns `MKMapItem`, which carries more than
298
+ a placemark: an `MKAddress` and `MKAddressRepresentations` for formatting.
299
+ Both initializers are failable; `mapItems` is an async throwing property.
272
300
 
273
301
  ```swift
274
- let geocoder = CLGeocoder()
302
+ @available(iOS 26, *)
303
+ func lookUp(_ text: String) async throws -> MKMapItem? {
304
+ guard let request = MKGeocodingRequest(addressString: text) else { return nil }
305
+ return try await request.mapItems.first
306
+ }
307
+ ```
308
+
309
+ Reverse lookup is `MKReverseGeocodingRequest(location:)`. Formatting and
310
+ batch lookups are in [Geocoding and Places on iOS 26](references/mapkit-patterns.md#geocoding-and-places-on-ios-26).
311
+
312
+ ### CLGeocoder (iOS 5 to iOS 25, deprecated in iOS 26)
275
313
 
276
- // Forward geocoding: address string -> coordinates
277
- let placemarks = try await geocoder.geocodeAddressString("1 Apple Park Way, Cupertino")
278
- if let location = placemarks.first?.location {
279
- print(location.coordinate) // CLLocationCoordinate2D
314
+ Use it only while the deployment target is below iOS 26. Every `CLPlacemark`
315
+ field is optional. `CLGeocoder` is not `Sendable`, so Swift 6 rejects one
316
+ shared global instance; make a geocoder for each lookup instead.
317
+
318
+ ```swift
319
+ func coordinate(for address: String) async throws -> CLLocationCoordinate2D? {
320
+ try await CLGeocoder().geocodeAddressString(address).first?.location?.coordinate
280
321
  }
281
322
 
282
- // Reverse geocoding: coordinates -> placemark
283
- let location = CLLocation(latitude: 37.3349, longitude: -122.0090)
284
- let placemarks = try await geocoder.reverseGeocodeLocation(location)
285
- if let placemark = placemarks.first {
286
- let address = [placemark.name, placemark.locality, placemark.administrativeArea]
323
+ func label(for spot: CLLocation) async throws -> String {
324
+ let marks = try await CLGeocoder().reverseGeocodeLocation(spot)
325
+ guard let mark = marks.first else { return "" }
326
+ return [mark.name, mark.locality, mark.administrativeArea]
287
327
  .compactMap { $0 }
288
328
  .joined(separator: ", ")
289
329
  }
290
330
  ```
291
331
 
292
- ### MKGeocodingRequest and MKReverseGeocodingRequest (iOS 26+)
293
-
294
- New MapKit-native geocoding returns `MKMapItem` with richer data and `MKAddress`
295
- / `MKAddressRepresentations` for flexible address formatting. Construct
296
- `MKGeocodingRequest(addressString:)` or `MKReverseGeocodingRequest(location:)` and
297
- await `.mapItems`. See [references/mapkit-patterns.md](references/mapkit-patterns.md) ("iOS 26 New
298
- APIs") for both, plus `MKAddressRepresentations` formatting.
299
-
300
332
  ## Search
301
333
 
302
- ### MKLocalSearchCompleter (Autocomplete)
303
-
304
- Set `queryFragment` on an `MKLocalSearchCompleter` and read `results` from its
305
- delegate for suggestions. Debounce input (300ms+) and constrain `completer.region`
306
- to the visible map region.
334
+ ### MKLocalSearchCompleter (autocomplete)
307
335
 
308
- ### MKLocalSearch (Full Search)
336
+ Set `queryFragment` and read `results` from the delegate. Debounce input by
337
+ 300 ms or more and set `completer.region` to the visible map region so
338
+ suggestions stay local.
309
339
 
310
- Convert a selected completion (or a natural-language query) into full `MKMapItem`
311
- results:
340
+ ### MKLocalSearch (full results)
312
341
 
313
342
  ```swift
314
- func search(for completion: MKLocalSearchCompletion) async throws -> [MKMapItem] {
315
- let request = MKLocalSearch.Request(completion: completion)
343
+ func places(for pick: MKLocalSearchCompletion) async throws -> [MKMapItem] {
344
+ let request = MKLocalSearch.Request(completion: pick)
316
345
  request.resultTypes = [.pointOfInterest, .address]
317
- let response = try await MKLocalSearch(request: request).start()
318
- return response.mapItems
346
+ let reply = try await MKLocalSearch(request: request).start()
347
+ return reply.mapItems
319
348
  }
320
349
  ```
321
350
 
322
- For a natural-language query, set `request.naturalLanguageQuery` and
323
- `request.region` instead. See [references/mapkit-patterns.md](references/mapkit-patterns.md) ("Search
324
- with Autocomplete") for the full completer delegate class and a `.searchable`
325
- view integration.
351
+ For free text, set `request.naturalLanguageQuery` and `request.region`
352
+ instead of passing a completion. The delegate-based service and the
353
+ `.searchable` screen are in
354
+ [Autocomplete Search](references/mapkit-patterns.md#autocomplete-search).
326
355
 
327
356
  ## Directions
328
357
 
358
+ `MKMapItem` and `MKRoute` are not `Sendable`. Keep the helper on the main
359
+ actor, where the SwiftUI view that calls it already runs, so the items never
360
+ cross an isolation boundary:
361
+
329
362
  ```swift
330
- func getDirections(from source: MKMapItem, to destination: MKMapItem,
331
- transport: MKDirectionsTransportType = .automobile) async throws -> MKRoute? {
363
+ @MainActor
364
+ func fastestRoute(
365
+ from start: MKMapItem,
366
+ to end: MKMapItem,
367
+ by mode: MKDirectionsTransportType = .automobile
368
+ ) async throws -> MKRoute? {
332
369
  let request = MKDirections.Request()
333
- request.source = source
334
- request.destination = destination
335
- request.transportType = transport
336
- let directions = MKDirections(request: request)
337
- let response = try await directions.calculate()
338
- return response.routes.first
370
+ request.source = start
371
+ request.destination = end
372
+ request.transportType = mode
373
+ let reply = try await MKDirections(request: request).calculate()
374
+ return reply.routes.first
339
375
  }
340
376
  ```
341
377
 
342
- ### Display Route on Map
378
+ ### Drawing the route
343
379
 
344
380
  ```swift
345
- @State private var route: MKRoute?
381
+ struct FerryRouteMap: View {
382
+ let pier: MKMapItem
383
+ let island: MKMapItem
384
+ @State private var route: MKRoute?
346
385
 
347
- Map {
348
- if let route {
349
- MapPolyline(route.polyline)
350
- .stroke(.blue, lineWidth: 5)
386
+ var body: some View {
387
+ Map {
388
+ if let route {
389
+ MapPolyline(route.polyline).stroke(.teal, lineWidth: 5)
390
+ }
391
+ Marker(item: pier)
392
+ Marker(item: island)
393
+ }
394
+ .task { route = try? await fastestRoute(from: pier, to: island) }
351
395
  }
352
- Marker("Start", coordinate: startCoord)
353
- Marker("End", coordinate: endCoord)
354
- }
355
- .task {
356
- route = try? await getDirections(from: startItem, to: endItem)
357
396
  }
358
397
  ```
359
398
 
360
- ### ETA and Cycling Directions
399
+ ### Travel time only, and cycling
361
400
 
362
- For travel time only, use `MKDirections.calculateETA()` (returns
363
- `expectedTravelTime` without route geometry). For bike routes, set
364
- `request.transportType = .cycling` (iOS 14+). See
365
- [references/mapkit-patterns.md](references/mapkit-patterns.md) ("ETA Calculation" and "Cycling
366
- Directions") for both.
401
+ - `MKDirections.calculateETA()` returns `expectedTravelTime` without route
402
+ geometry; use it when a label is all you need
403
+ ([ETA Calculation](references/mapkit-patterns.md#eta-calculation)).
404
+ - Bike routes: `request.transportType = .cycling`, iOS 14 and later
405
+ ([Cycling Directions](references/mapkit-patterns.md#cycling-directions-ios-14)).
367
406
 
368
407
  ## PlaceDescriptor (iOS 26+)
369
408
 
370
- Create rich place references from coordinates or addresses without needing a
371
- Place ID. Requires `import GeoToolbox`.
409
+ `PlaceDescriptor`, from `GeoToolbox`, describes a place by coordinate or
410
+ address when you have no MapKit place ID. `MKMapItemRequest` resolves it into
411
+ a full `MKMapItem`.
372
412
 
373
413
  ```swift
374
414
  import GeoToolbox
415
+ import MapKit
375
416
 
376
417
  @available(iOS 26, *)
377
- func lookupPlace(name: String, coordinate: CLLocationCoordinate2D) async throws -> MKMapItem {
378
- let descriptor = PlaceDescriptor(
379
- representations: [.coordinate(coordinate)],
380
- commonName: name
381
- )
382
- let request = MKMapItemRequest(placeDescriptor: descriptor)
383
- return try await request.mapItem
418
+ func mapItem(near point: CLLocationCoordinate2D, named name: String) async throws -> MKMapItem {
419
+ let place = PlaceDescriptor(representations: [.coordinate(point)], commonName: name)
420
+ return try await MKMapItemRequest(placeDescriptor: place).mapItem
384
421
  }
385
422
  ```
386
423
 
387
424
  ## Common Mistakes
388
425
 
389
- **DON'T:** Request always authorization upfront.
390
- **DO:** Start with when-in-use authorization. On iOS 18+, hold a `CLServiceSession`
391
- for the feature lifetime; request `.always` only for background features that
392
- need system relaunch after termination.
393
-
394
- **DON'T:** Use `CLLocationManagerDelegate` for simple location fetches on iOS 17+.
395
- **DO:** Use `CLLocationUpdate.liveUpdates()` async stream for cleaner, more concise code.
396
-
397
- **DON'T:** Ignore `CLLocationUpdate` diagnostics such as denied, globally denied, or unavailable location.
398
- **DO:** Stop or degrade the feature, show recovery UI such as Settings guidance, and keep search/manual flows usable.
399
-
400
- **DON'T:** Let `liveUpdates()` run from an unowned task after the map/view is gone.
401
- **DO:** Store the `Task`, cancel it when the feature stops, and filter invalid, inaccurate, stale, or impossible movement fixes.
402
-
403
- **DON'T:** Force-unwrap `CLPlacemark` properties - they are all optional.
404
- **DO:** Use nil-coalescing: `placemark.locality ?? "Unknown"`.
405
-
406
- **DON'T:** Fire `MKLocalSearchCompleter` queries on every keystroke.
407
- **DO:** Debounce with `.task(id: searchText)` + `Task.sleep(for: .milliseconds(300))`.
408
-
409
- **DON'T:** Silently fail when location authorization is denied.
410
- **DO:** Detect `.denied` status and show an alert with a Settings deep link.
411
-
412
- **DON'T:** Assume geocoding always succeeds - handle empty results and network errors.
426
+ | Mistake | Do instead |
427
+ |---------|-----------|
428
+ | Asking for Always authorization at launch | Start with when-in-use; ask for `.always` only for a background feature that needs relaunch after termination |
429
+ | No `CLServiceSession` on iOS 18+ | Hold one for the life of the feature |
430
+ | A `CLLocationManagerDelegate` just to read position on iOS 17+ | Iterate `liveUpdates()`; less code, same result |
431
+ | Ignoring diagnostics (denied, off system-wide, unavailable) | Switch to a reduced mode, point the user at Settings, and leave search and manual entry usable |
432
+ | `liveUpdates()` in a task nobody owns | Keep the `Task` in a property and cancel it with the screen; filter bad fixes |
433
+ | Force-unwrapping `CLPlacemark` fields | They are all optional: `mark.locality ?? "Unknown"` |
434
+ | Querying the completer on every keystroke | `.task(id: text)` plus `Task.sleep(for: .milliseconds(300))` |
435
+ | Silent failure when denied | Detect `.denied` and offer a Settings link |
436
+ | Assuming geocoding returns something | Plan for zero matches and for being offline |
413
437
 
414
438
  ## Review Checklist
415
439
 
416
- - [ ] Info.plist has `NSLocationWhenInUseUsageDescription` with specific reason
417
- - [ ] Authorization denial handled with Settings deep link
418
- - [ ] `CLLocationUpdate` task cancelled when not needed (battery)
419
- - [ ] Location accuracy appropriate for the use case
420
- - [ ] Map annotations use `Identifiable` data with stable IDs
421
- - [ ] Geocoding errors handled (network failure, no results)
422
- - [ ] Search completer input debounced
423
- - [ ] `CLMonitor` limited to 20 conditions, instance kept alive
440
+ - [ ] `NSLocationWhenInUseUsageDescription` is present and names a concrete benefit
441
+ - [ ] A denied user gets an explanation and a Settings deep link
442
+ - [ ] The `CLLocationUpdate` task is cancelled when not needed, to save battery
443
+ - [ ] Requested accuracy matches what the feature needs
444
+ - [ ] Annotation data is `Identifiable` with stable IDs
445
+ - [ ] Geocoding handles network failure and empty results
446
+ - [ ] Completer input is debounced
447
+ - [ ] `CLMonitor` stays at or under 20 conditions and the instance is kept alive
424
448
  - [ ] Background location uses `CLBackgroundActivitySession`
425
- - [ ] Map tested with VoiceOver
426
- - [ ] Map annotation view models and location UI updates are `@MainActor`-isolated
449
+ - [ ] The map has been tried with VoiceOver
450
+ - [ ] Annotation models and location-driven UI state are `@MainActor`
427
451
 
428
452
  ## References
429
453
 
430
- - [references/mapkit-patterns.md](references/mapkit-patterns.md) - Map setup, annotations, search, routes, clustering, Look Around, snapshots.
431
- - [references/mapkit-corelocation-patterns.md](references/mapkit-corelocation-patterns.md) - CLLocationUpdate, CLMonitor, CLServiceSession, background location, testing.
454
+ - [Map patterns](references/mapkit-patterns.md): map setup,
455
+ annotations, camera, search, routes, dense maps and clustering, Look Around,
456
+ snapshots, iOS 26 APIs.
457
+ - [Location patterns](references/mapkit-corelocation-patterns.md):
458
+ `CLLocationUpdate`, `CLServiceSession`, `CLMonitor`, background location,
459
+ testing, privacy keys.