@mmerterden/multi-agent-pipeline 20.7.0 → 20.8.1

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 (284) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +0 -10
  3. package/docs/facts.json +1 -1
  4. package/manifest.json +285 -285
  5. package/package.json +3 -3
  6. package/pipeline/lib/redact.mjs +3 -2
  7. package/pipeline/scripts/_notices.mjs +1 -1
  8. package/pipeline/scripts/gen-skills-index.mjs +13 -1
  9. package/pipeline/scripts/pre-commit-check.sh +4 -0
  10. package/pipeline/skills/.skill-manifest.json +69 -69
  11. package/pipeline/skills/shared/README.md +70 -70
  12. package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
  13. package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
  14. package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
  15. package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
  16. package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
  17. package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
  18. package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
  19. package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
  20. package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
  21. package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
  22. package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
  23. package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +345 -277
  24. package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
  25. package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +107 -121
  26. package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +145 -165
  27. package/pipeline/skills/shared/external/app-store-review/SKILL.md +306 -326
  28. package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
  29. package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
  30. package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
  31. package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +335 -360
  32. package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
  33. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
  34. package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
  35. package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
  36. package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
  37. package/pipeline/skills/shared/external/authentication/SKILL.md +277 -381
  38. package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
  39. package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +135 -178
  40. package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
  41. package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
  42. package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
  43. package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
  44. package/pipeline/skills/shared/external/background-processing/SKILL.md +274 -384
  45. package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
  46. package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +173 -321
  47. package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
  48. package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
  49. package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
  50. package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
  51. package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
  52. package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
  53. package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
  54. package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
  55. package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
  56. package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +228 -376
  57. package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
  58. package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
  59. package/pipeline/skills/shared/external/core-data/SKILL.md +302 -368
  60. package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
  61. package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
  62. package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
  63. package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
  64. package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
  65. package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
  66. package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
  67. package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
  68. package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
  69. package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
  70. package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
  71. package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
  72. package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
  73. package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
  74. package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
  75. package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
  76. package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
  77. package/pipeline/skills/shared/external/device-integrity/SKILL.md +236 -353
  78. package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
  79. package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
  80. package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
  81. package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
  82. package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
  83. package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
  84. package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
  85. package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
  86. package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
  87. package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
  88. package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
  89. package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
  90. package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
  91. package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
  92. package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
  93. package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
  94. package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
  95. package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
  96. package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
  97. package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
  98. package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
  99. package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
  100. package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
  101. package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
  102. package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
  103. package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
  104. package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
  105. package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
  106. package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
  107. package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
  108. package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
  109. package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
  110. package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
  111. package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
  112. package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
  113. package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
  114. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +3 -3
  115. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +1 -1
  116. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +8 -7
  117. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +2 -2
  118. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +5 -2
  119. package/pipeline/skills/shared/external/localization-reuse-map/scripts/_shared.py +100 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +45 -26
  121. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +14 -16
  122. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +12 -5
  123. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +2 -1
  124. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +6 -5
  125. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +44 -18
  126. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +5 -2
  127. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +10 -11
  128. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +4 -33
  129. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +12 -59
  130. package/pipeline/skills/shared/external/mapkit-location/SKILL.md +297 -267
  131. package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
  132. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
  133. package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
  134. package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
  135. package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
  136. package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
  137. package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
  138. package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
  139. package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
  140. package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
  141. package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
  142. package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
  143. package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
  144. package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
  145. package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
  146. package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
  147. package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
  148. package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
  149. package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
  150. package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
  151. package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
  152. package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
  153. package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
  154. package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
  155. package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
  156. package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
  157. package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
  158. package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
  159. package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
  160. package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
  161. package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
  162. package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
  163. package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
  164. package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
  165. package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
  166. package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
  167. package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
  168. package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
  169. package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
  170. package/pipeline/skills/shared/external/skill-creator/template.md +7 -1
  171. package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
  172. package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
  173. package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
  174. package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
  175. package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
  176. package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
  177. package/pipeline/skills/shared/external/storekit/references/core-patterns.md +302 -241
  178. package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
  179. package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
  180. package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
  181. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
  182. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
  183. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
  184. package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
  185. package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
  186. package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
  187. package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
  188. package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
  189. package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
  190. package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
  191. package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
  192. package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +304 -351
  193. package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
  194. package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
  195. package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
  196. package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
  197. package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
  198. package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
  199. package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
  200. package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
  201. package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
  202. package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
  203. package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
  204. package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
  205. package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
  206. package/pipeline/skills/shared/external/swift-security/SKILL.md +183 -162
  207. package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
  208. package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
  209. package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +411 -476
  210. package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
  211. package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
  212. package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
  213. package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
  214. package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
  215. package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
  216. package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +375 -491
  217. package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
  218. package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
  219. package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
  220. package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +397 -457
  221. package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
  222. package/pipeline/skills/shared/external/swift-testing/SKILL.md +191 -175
  223. package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
  224. package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +81 -84
  225. package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
  226. package/pipeline/skills/shared/external/swiftdata/SKILL.md +394 -256
  227. package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
  228. package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
  229. package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
  230. package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
  231. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
  232. package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
  233. package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
  234. package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
  235. package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
  236. package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
  237. package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
  238. package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
  239. package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
  240. package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
  241. package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
  242. package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
  243. package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
  244. package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
  245. package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
  246. package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
  247. package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
  248. package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
  249. package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
  250. package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
  251. package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +201 -168
  252. package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
  253. package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +134 -133
  254. package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
  255. package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +111 -138
  256. package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
  257. package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
  258. package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
  259. package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
  260. package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
  261. package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
  262. package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
  263. package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
  264. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
  265. package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
  266. package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
  267. package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
  268. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
  269. package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
  270. package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
  271. package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
  272. package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
  273. package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
  274. package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
  275. package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
  276. package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
  277. package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
  278. package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
  279. package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
  280. package/pipeline/skills/shared/external/weatherkit/SKILL.md +160 -315
  281. package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
  282. package/pipeline/skills/shared/external/widgetkit/SKILL.md +224 -288
  283. package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +416 -719
  284. 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,170 @@ 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 (available since iOS 5, 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. The SDK's deprecation
315
+ messages point reverse lookups to `MKReverseGeocodingRequest` and forward
316
+ lookups to `MKGeocodingRequest`. Every `CLPlacemark`
317
+ field is optional. `CLGeocoder` is not `Sendable`, so Swift 6 rejects one
318
+ shared global instance; make a geocoder for each lookup instead.
319
+
320
+ ```swift
321
+ func coordinate(for address: String) async throws -> CLLocationCoordinate2D? {
322
+ try await CLGeocoder().geocodeAddressString(address).first?.location?.coordinate
280
323
  }
281
324
 
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]
325
+ func label(for spot: CLLocation) async throws -> String {
326
+ let marks = try await CLGeocoder().reverseGeocodeLocation(spot)
327
+ guard let mark = marks.first else { return "" }
328
+ return [mark.name, mark.locality, mark.administrativeArea]
287
329
  .compactMap { $0 }
288
330
  .joined(separator: ", ")
289
331
  }
290
332
  ```
291
333
 
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
334
  ## Search
301
335
 
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.
336
+ ### MKLocalSearchCompleter (autocomplete)
307
337
 
308
- ### MKLocalSearch (Full Search)
338
+ Set `queryFragment` and read `results` from the delegate. Debounce input by
339
+ 300 ms or more and set `completer.region` to the visible map region so
340
+ suggestions stay local.
309
341
 
310
- Convert a selected completion (or a natural-language query) into full `MKMapItem`
311
- results:
342
+ ### MKLocalSearch (full results)
312
343
 
313
344
  ```swift
314
- func search(for completion: MKLocalSearchCompletion) async throws -> [MKMapItem] {
315
- let request = MKLocalSearch.Request(completion: completion)
345
+ func places(for pick: MKLocalSearchCompletion) async throws -> [MKMapItem] {
346
+ let request = MKLocalSearch.Request(completion: pick)
316
347
  request.resultTypes = [.pointOfInterest, .address]
317
- let response = try await MKLocalSearch(request: request).start()
318
- return response.mapItems
348
+ let reply = try await MKLocalSearch(request: request).start()
349
+ return reply.mapItems
319
350
  }
320
351
  ```
321
352
 
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.
353
+ For free text, set `request.naturalLanguageQuery` and `request.region`
354
+ instead of passing a completion. The delegate-based service and the
355
+ `.searchable` screen are in
356
+ [Autocomplete Search](references/mapkit-patterns.md#autocomplete-search).
326
357
 
327
358
  ## Directions
328
359
 
360
+ `MKMapItem` and `MKRoute` are not `Sendable`. Keep the helper on the main
361
+ actor, where the SwiftUI view that calls it already runs, so the items never
362
+ cross an isolation boundary:
363
+
329
364
  ```swift
330
- func getDirections(from source: MKMapItem, to destination: MKMapItem,
331
- transport: MKDirectionsTransportType = .automobile) async throws -> MKRoute? {
365
+ @MainActor
366
+ func fastestRoute(
367
+ from start: MKMapItem,
368
+ to end: MKMapItem,
369
+ by mode: MKDirectionsTransportType = .automobile
370
+ ) async throws -> MKRoute? {
332
371
  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
372
+ request.source = start
373
+ request.destination = end
374
+ request.transportType = mode
375
+ let reply = try await MKDirections(request: request).calculate()
376
+ return reply.routes.first
339
377
  }
340
378
  ```
341
379
 
342
- ### Display Route on Map
380
+ ### Drawing the route
343
381
 
344
382
  ```swift
345
- @State private var route: MKRoute?
383
+ struct FerryRouteMap: View {
384
+ let pier: MKMapItem
385
+ let island: MKMapItem
386
+ @State private var route: MKRoute?
346
387
 
347
- Map {
348
- if let route {
349
- MapPolyline(route.polyline)
350
- .stroke(.blue, lineWidth: 5)
388
+ var body: some View {
389
+ Map {
390
+ if let route {
391
+ MapPolyline(route.polyline).stroke(.teal, lineWidth: 5)
392
+ }
393
+ Marker(item: pier)
394
+ Marker(item: island)
395
+ }
396
+ .task { route = try? await fastestRoute(from: pier, to: island) }
351
397
  }
352
- Marker("Start", coordinate: startCoord)
353
- Marker("End", coordinate: endCoord)
354
- }
355
- .task {
356
- route = try? await getDirections(from: startItem, to: endItem)
357
398
  }
358
399
  ```
359
400
 
360
- ### ETA and Cycling Directions
401
+ ### Travel time only, and cycling
361
402
 
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.
403
+ - `MKDirections.calculateETA()` returns `expectedTravelTime` without route
404
+ geometry; use it when a label is all you need
405
+ ([ETA Calculation](references/mapkit-patterns.md#eta-calculation)).
406
+ - Bike routes: `request.transportType = .cycling`, iOS 14 and later
407
+ ([Cycling Directions](references/mapkit-patterns.md#cycling-directions-ios-14)).
367
408
 
368
409
  ## PlaceDescriptor (iOS 26+)
369
410
 
370
- Create rich place references from coordinates or addresses without needing a
371
- Place ID. Requires `import GeoToolbox`.
411
+ `PlaceDescriptor`, from `GeoToolbox`, describes a place by coordinate or
412
+ address when you have no MapKit place ID. `MKMapItemRequest` resolves it into
413
+ a full `MKMapItem`.
372
414
 
373
415
  ```swift
374
416
  import GeoToolbox
417
+ import MapKit
375
418
 
376
419
  @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
420
+ func mapItem(near point: CLLocationCoordinate2D, named name: String) async throws -> MKMapItem {
421
+ let place = PlaceDescriptor(representations: [.coordinate(point)], commonName: name)
422
+ return try await MKMapItemRequest(placeDescriptor: place).mapItem
384
423
  }
385
424
  ```
386
425
 
387
426
  ## Common Mistakes
388
427
 
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.
428
+ | Mistake | Do instead |
429
+ |---------|-----------|
430
+ | Asking for Always authorization at launch | Start with when-in-use; ask for `.always` only for a background feature that needs relaunch after termination |
431
+ | No `CLServiceSession` on iOS 18+ | Hold one for the life of the feature |
432
+ | A `CLLocationManagerDelegate` just to read position on iOS 17+ | Iterate `liveUpdates()`; less code, same result |
433
+ | Ignoring diagnostics (denied, off system-wide, unavailable) | Switch to a reduced mode, point the user at Settings, and leave search and manual entry usable |
434
+ | `liveUpdates()` in a task nobody owns | Keep the `Task` in a property and cancel it with the screen; filter bad fixes |
435
+ | Force-unwrapping `CLPlacemark` fields | They are all optional: `mark.locality ?? "Unknown"` |
436
+ | Querying the completer on every keystroke | `.task(id: text)` plus `Task.sleep(for: .milliseconds(300))` |
437
+ | Silent failure when denied | Detect `.denied` and offer a Settings link |
438
+ | Assuming geocoding returns something | Plan for zero matches and for being offline |
413
439
 
414
440
  ## Review Checklist
415
441
 
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
442
+ - [ ] `NSLocationWhenInUseUsageDescription` is present and names a concrete benefit
443
+ - [ ] A denied user gets an explanation and a Settings deep link
444
+ - [ ] The `CLLocationUpdate` task is cancelled when not needed, to save battery
445
+ - [ ] Requested accuracy matches what the feature needs
446
+ - [ ] Annotation data is `Identifiable` with stable IDs
447
+ - [ ] Geocoding handles network failure and empty results
448
+ - [ ] Completer input is debounced
449
+ - [ ] `CLMonitor` stays at or under 20 conditions and the instance is kept alive
424
450
  - [ ] Background location uses `CLBackgroundActivitySession`
425
- - [ ] Map tested with VoiceOver
426
- - [ ] Map annotation view models and location UI updates are `@MainActor`-isolated
451
+ - [ ] The map has been tried with VoiceOver
452
+ - [ ] Annotation models and location-driven UI state are `@MainActor`
427
453
 
428
454
  ## References
429
455
 
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.
456
+ - [Map patterns](references/mapkit-patterns.md): map setup,
457
+ annotations, camera, search, routes, dense maps and clustering, Look Around,
458
+ snapshots, iOS 26 APIs.
459
+ - [Location patterns](references/mapkit-corelocation-patterns.md):
460
+ `CLLocationUpdate`, `CLServiceSession`, `CLMonitor`, background location,
461
+ testing, privacy keys.