@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,500 +1,468 @@
1
1
  ---
2
2
  name: pdfkit
3
- description: "Display and manipulate PDF documents using PDFKit. Use when embedding PDFView to show PDF files, creating or modifying PDFDocument instances, adding annotations (highlights, notes, signature widgets), extracting text with PDFSelection, navigating pages, generating thumbnails, filling PDF forms, or wrapping PDFView in SwiftUI."
3
+ description: "PDFKit on iOS: PDFView display and SwiftUI wrapping, creating and editing PDFDocument and PDFPage, highlight, note, signature and form annotations, PDFSelection search and text extraction, page navigation, thumbnails, form filling, encrypted saving. Use when an app displays, searches, annotates, fills, builds or saves PDFs."
4
4
  metadata:
5
- source: "dpearson2699/swift-ios-skills (PolyForm Perimeter 1.0.0)"
5
+ source: multi-agent-pipeline
6
6
  ---
7
- # PDFKit
8
7
 
9
- Display, navigate, search, annotate, and manipulate PDF documents with `PDFView`, `PDFDocument`, `PDFPage`, `PDFAnnotation`, and `PDFSelection`. Targets Swift 6.3 / iOS 26+.
8
+ # PDFKit
10
9
 
11
- ## Contents
10
+ PDFKit renders, searches and edits PDF files. Most work touches five types:
11
+ `PDFView` (the on-screen viewer), `PDFDocument` (the file), `PDFPage` (one
12
+ page), `PDFAnnotation` (marks and form fields on a page) and `PDFSelection`
13
+ (a run of text). Examples target Swift 6.3 and iOS 26.
12
14
 
13
- - [Setup](#setup)
14
- - [Displaying PDFs](#displaying-pdfs)
15
- - [Loading Documents](#loading-documents)
16
- - [Page Navigation](#page-navigation)
17
- - [Text Search and Selection](#text-search-and-selection)
18
- - [Annotations](#annotations)
19
- - [Thumbnails](#thumbnails)
20
- - [SwiftUI Integration](#swiftui-integration)
21
- - [Common Mistakes](#common-mistakes)
22
- - [Review Checklist](#review-checklist)
23
- - [References](#references)
15
+ Freehand drawing tools are not PDFKit work: use PencilKit or PaperKit.
24
16
 
25
17
  ## Setup
26
18
 
27
- PDFKit requires no entitlements or Info.plist entries.
19
+ No entitlement and no Info.plist key is needed.
28
20
 
29
21
  ```swift
30
22
  import PDFKit
31
23
  ```
32
24
 
33
- **Platform availability:** iOS 11+, iPadOS 11+, Mac Catalyst 13.1+, macOS 10.4+, tvOS 11+, visionOS 1.0+.
25
+ | Platform | Minimum |
26
+ |---|---|
27
+ | iOS, iPadOS | 11 |
28
+ | Mac Catalyst | 13.1 |
29
+ | macOS | 10.4 |
30
+ | tvOS | 11 |
31
+ | visionOS | 1.0 |
34
32
 
35
- ## Displaying PDFs
33
+ ## Showing a PDF
36
34
 
37
- `PDFView` is a `UIView` subclass that renders PDF content, handles zoom,
38
- scroll, text selection, and page navigation out of the box.
35
+ `PDFView` is a `UIView` subclass. Out of the box it zooms, scrolls, selects text
36
+ and pages through the document.
39
37
 
40
38
  ```swift
41
39
  import PDFKit
42
40
  import UIKit
43
41
 
44
- class PDFViewController: UIViewController {
45
- let pdfView = PDFView()
42
+ final class ManualViewController: UIViewController {
43
+ private let reader = PDFView()
46
44
 
47
45
  override func viewDidLoad() {
48
46
  super.viewDidLoad()
49
- pdfView.frame = view.bounds
50
- pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
51
- view.addSubview(pdfView)
52
-
53
- pdfView.autoScales = true
54
- pdfView.displayMode = .singlePageContinuous
55
- pdfView.displayDirection = .vertical
56
-
57
- if let url = Bundle.main.url(forResource: "sample", withExtension: "pdf") {
58
- pdfView.document = PDFDocument(url: url)
47
+ reader.frame = view.bounds
48
+ reader.autoresizingMask = [.flexibleWidth, .flexibleHeight]
49
+ reader.autoScales = true
50
+ reader.displayMode = .singlePageContinuous
51
+ reader.displayDirection = .vertical
52
+ view.addSubview(reader)
53
+
54
+ if let url = Bundle.main.url(forResource: "assembly-guide", withExtension: "pdf"),
55
+ let file = PDFDocument(url: url) {
56
+ reader.document = file
59
57
  }
60
58
  }
61
59
  }
62
60
  ```
63
61
 
64
- ### Display Modes
62
+ ### Display modes
65
63
 
66
- | Mode | Behavior |
64
+ | Mode | Layout |
67
65
  |---|---|
68
- | `.singlePage` | One page at a time |
69
- | `.singlePageContinuous` | Pages stacked vertically, scrollable |
70
- | `.twoUp` | Two pages side by side |
71
- | `.twoUpContinuous` | Two-up with continuous scrolling |
66
+ | `.singlePage` | one page on screen at a time |
67
+ | `.singlePageContinuous` | one column of pages, scrolling |
68
+ | `.twoUp` | facing pages side by side |
69
+ | `.twoUpContinuous` | facing pages, scrolling |
72
70
 
73
- ### Scaling and Appearance
71
+ ### Scale and look
74
72
 
75
73
  ```swift
76
- pdfView.autoScales = true
77
- pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
78
- pdfView.maxScaleFactor = 4.0
74
+ import PDFKit
79
75
 
80
- pdfView.displaysPageBreaks = true
81
- pdfView.pageShadowsEnabled = true
82
- pdfView.interpolationQuality = .high
76
+ @MainActor
77
+ func tune(_ reader: PDFView) {
78
+ reader.autoScales = true
79
+ reader.minScaleFactor = reader.scaleFactorForSizeToFit
80
+ reader.maxScaleFactor = 5.0
81
+ reader.displaysPageBreaks = true
82
+ reader.pageShadowsEnabled = false
83
+ reader.interpolationQuality = .high
84
+ }
83
85
  ```
84
86
 
85
- ## Loading Documents
87
+ ## Loading documents
86
88
 
87
- `PDFDocument` loads from a URL, `Data`, or can be created empty.
89
+ There are three initializers: `PDFDocument(url:)`, `PDFDocument(data:)` and
90
+ the empty `PDFDocument()`. The first two are failable.
88
91
 
89
- ```swift
90
- let fileDoc = PDFDocument(url: fileURL)
91
- let dataDoc = PDFDocument(data: pdfData)
92
- let emptyDoc = PDFDocument()
93
- ```
94
-
95
- ### Password-Protected PDFs
92
+ ### Locked files
96
93
 
97
94
  ```swift
98
- guard let document = PDFDocument(url: url) else { return }
99
- if document.isLocked {
100
- if !document.unlock(withPassword: userPassword) {
101
- // Show password prompt
102
- }
95
+ import PDFKit
96
+
97
+ func open(_ file: PDFDocument, passcode: String) -> Bool {
98
+ guard file.isLocked else { return true }
99
+ return file.unlock(withPassword: passcode)
103
100
  }
104
101
  ```
105
102
 
106
- ### Saving and Page Manipulation
103
+ If `unlock(withPassword:)` returns `false`, ask the user for the password again.
104
+
105
+ ### Saving and rearranging pages
107
106
 
108
107
  ```swift
109
- document.write(to: outputURL)
110
- document.write(to: outputURL, withOptions: [
111
- .ownerPasswordOption: "ownerPass", .userPasswordOption: "userPass"
112
- ])
113
- let data = document.dataRepresentation()
114
-
115
- // Pages are zero-based. Validate indices; out-of-range calls raise exceptions.
116
- let count = document.pageCount
117
- document.insert(PDFPage(), at: count)
118
- if document.pageCount > 2 {
119
- document.removePage(at: 2)
108
+ import PDFKit
109
+
110
+ func export(_ file: PDFDocument, to url: URL, ownerKey: String, readerKey: String) -> Bool {
111
+ file.write(to: url, withOptions: [
112
+ .ownerPasswordOption: ownerKey,
113
+ .userPasswordOption: readerKey
114
+ ])
120
115
  }
121
- if document.pageCount > 3 {
122
- document.exchangePage(at: 0, withPageAt: 3)
116
+
117
+ func reorder(_ file: PDFDocument) {
118
+ let blank = PDFPage()
119
+ file.insert(blank, at: file.pageCount)
120
+ if file.pageCount > 2 {
121
+ file.exchangePage(at: 0, withPageAt: 2)
122
+ }
123
+ if file.pageCount > 1 {
124
+ file.removePage(at: 1)
125
+ }
123
126
  }
124
127
  ```
125
128
 
126
- ## Page Navigation
127
-
128
- `PDFView` provides built-in navigation with history tracking.
129
-
130
- ```swift
131
- // Go to a specific page
132
- let pageIndex = 5
133
- if let document = pdfView.document,
134
- pageIndex >= 0,
135
- pageIndex < document.pageCount,
136
- let page = document.page(at: pageIndex) {
137
- pdfView.go(to: page)
138
- }
129
+ - `write(to:)` saves as is; `write(to:withOptions:)` with
130
+ `.ownerPasswordOption` and `.userPasswordOption` encrypts.
131
+ - `dataRepresentation()` returns `Data?` for upload or sharing.
132
+ - Page indices start at 0. Inserting at `pageCount` appends.
133
+ - An index outside `0..<pageCount` raises an Objective-C exception rather than
134
+ returning `nil`, so check it before `page(at:)`, `insert(_:at:)`,
135
+ `removePage(at:)` or `exchangePage(at:withPageAt:)`.
139
136
 
140
- // Sequential navigation
141
- pdfView.goToNextPage(nil)
142
- pdfView.goToPreviousPage(nil)
143
- pdfView.goToFirstPage(nil)
144
- pdfView.goToLastPage(nil)
137
+ ## Navigating
145
138
 
146
- // Check navigation state
147
- if pdfView.canGoToNextPage { /* ... */ }
139
+ `PDFView` keeps its own history of where the user has been.
148
140
 
149
- // History navigation
150
- if pdfView.canGoBack { pdfView.goBack(nil) }
141
+ ```swift
142
+ import PDFKit
151
143
 
152
- // Go to a specific point on the current page
153
- if let page = pdfView.currentPage {
154
- let destination = PDFDestination(page: page, at: CGPoint(x: 0, y: 500))
155
- pdfView.go(to: destination)
144
+ @MainActor
145
+ func show(pageNumber index: Int, in reader: PDFView) {
146
+ guard let file = reader.document, index >= 0, index < file.pageCount,
147
+ let target = file.page(at: index) else { return }
148
+ reader.go(to: target)
156
149
  }
157
- ```
158
150
 
159
- ### Observing Page Changes
151
+ @MainActor
152
+ func stepThrough(_ reader: PDFView) {
153
+ if reader.canGoToNextPage { reader.goToNextPage(nil) }
154
+ reader.goToPreviousPage(nil)
155
+ reader.goToFirstPage(nil)
156
+ reader.goToLastPage(nil)
157
+ if reader.canGoBack { reader.goBack(nil) }
158
+ }
160
159
 
161
- ```swift
162
- NotificationCenter.default.addObserver(
163
- self, selector: #selector(pageChanged),
164
- name: .PDFViewPageChanged, object: pdfView
165
- )
166
-
167
- @objc func pageChanged(_ notification: Notification) {
168
- guard let page = pdfView.currentPage,
169
- let doc = pdfView.document else { return }
170
- let index = doc.index(for: page)
171
- pageLabel.text = "Page \(index + 1) of \(doc.pageCount)"
160
+ @MainActor
161
+ func jump(to point: CGPoint, on page: PDFPage, in reader: PDFView) {
162
+ reader.go(to: PDFDestination(page: page, at: point))
163
+ _ = reader.currentPage
172
164
  }
173
165
  ```
174
166
 
175
- ## Text Search and Selection
176
-
177
- ### Synchronous Search
167
+ ### Tracking the current page
178
168
 
179
169
  ```swift
180
- let results: [PDFSelection] = document.findString(
181
- "search term", withOptions: [.caseInsensitive]
182
- )
170
+ import PDFKit
171
+
172
+ @MainActor
173
+ func watchPages(of reader: PDFView, update: @escaping @MainActor @Sendable (String) -> Void) -> NSObjectProtocol {
174
+ NotificationCenter.default.addObserver(forName: .PDFViewPageChanged, object: reader, queue: .main) { _ in
175
+ MainActor.assumeIsolated {
176
+ guard let file = reader.document, let page = reader.currentPage else { return }
177
+ update("\(file.index(for: page) + 1) / \(file.pageCount)")
178
+ }
179
+ }
180
+ }
183
181
  ```
184
182
 
185
- ### Asynchronous Search
183
+ ## Search and text
186
184
 
187
- Use `PDFDocumentDelegate` for background searches on large documents.
188
- Implement `didMatchString(_:)` to receive each match and
189
- `documentDidEndDocumentFind(_:)` for completion.
185
+ ### Synchronous
190
186
 
191
- ### Incremental Search and Find Interaction
187
+ `findString(_:withOptions:)` returns every match as `[PDFSelection]`:
192
188
 
193
189
  ```swift
194
- // Find next match from current selection
195
- let next = document.findString("term", fromSelection: current, withOptions: [.caseInsensitive])
190
+ import PDFKit
196
191
 
197
- // System find bar (iOS 16+)
198
- pdfView.isFindInteractionEnabled = true
192
+ func matches(of term: String, in file: PDFDocument) -> [PDFSelection] {
193
+ file.findString(term, withOptions: [.caseInsensitive])
194
+ }
199
195
  ```
200
196
 
201
- ### Text Extraction
197
+ ### Asynchronous
198
+
199
+ For long documents, search in the background with `beginFindString(_:withOptions:)`
200
+ and a `PDFDocumentDelegate`. `didMatchString(_:)` is called per hit and
201
+ `documentDidEndDocumentFind(_:)` when the pass finishes.
202
202
 
203
203
  ```swift
204
- let fullText = document.string // Entire document
205
- let firstPage = document.pageCount > 0 ? document.page(at: 0) : nil
206
- let pageText = firstPage?.string // Single page
207
- let attributed = firstPage?.attributedString // With formatting
208
-
209
- // Region-based extraction
210
- if let page = firstPage {
211
- let selection = page.selection(for: CGRect(x: 50, y: 50, width: 400, height: 200))
212
- let text = selection?.string
213
- }
214
- ```
204
+ import PDFKit
215
205
 
216
- ### Highlighting Search Results
206
+ final class ContractSearch: NSObject, PDFDocumentDelegate {
207
+ private(set) var hits: [PDFSelection] = []
208
+ var onFinish: (([PDFSelection]) -> Void)?
217
209
 
218
- ```swift
219
- let results = document.findString("important", withOptions: [.caseInsensitive])
220
- for selection in results { selection.color = .yellow }
221
- pdfView.highlightedSelections = results
210
+ func run(_ term: String, in file: PDFDocument) {
211
+ hits.removeAll()
212
+ file.delegate = self
213
+ file.beginFindString(term, withOptions: [.caseInsensitive])
214
+ }
222
215
 
223
- if let first = results.first {
224
- pdfView.setCurrentSelection(first, animate: true)
225
- pdfView.go(to: first)
216
+ func didMatchString(_ instance: PDFSelection) {
217
+ hits.append(instance)
218
+ }
219
+
220
+ func documentDidEndDocumentFind(_ notification: Notification) {
221
+ onFinish?(hits)
222
+ }
226
223
  }
227
224
  ```
228
225
 
229
- ## Annotations
226
+ ### Next match and the system find bar
230
227
 
231
- Annotations are created with `PDFAnnotation(bounds:forType:withProperties:)`
232
- and added to a `PDFPage`.
228
+ - `findString(_:fromSelection:withOptions:)` returns the first hit after a
229
+ given selection, which is how "Find next" works.
230
+ - `reader.isFindInteractionEnabled = true` turns on the system find bar
231
+ (iOS 16+).
233
232
 
234
- ### Highlight Annotation
233
+ ### Extracting text
235
234
 
236
235
  ```swift
237
- func addHighlight(to page: PDFPage, selection: PDFSelection) {
238
- let highlight = PDFAnnotation(
239
- bounds: selection.bounds(for: page),
240
- forType: .highlight, withProperties: nil
241
- )
242
- highlight.color = UIColor.yellow.withAlphaComponent(0.5)
243
- page.addAnnotation(highlight)
236
+ import PDFKit
237
+
238
+ func textSamples(from file: PDFDocument) -> (all: String?, first: String?, box: String?) {
239
+ let all = file.string
240
+ guard file.pageCount > 0, let first = file.page(at: 0) else { return (all, nil, nil) }
241
+ _ = first.attributedString
242
+ let box = first.selection(for: CGRect(x: 36, y: 700, width: 300, height: 60))?.string
243
+ return (all, first.string, box)
244
244
  }
245
245
  ```
246
246
 
247
- ### Text Note Annotation
248
-
249
- ```swift
250
- let note = PDFAnnotation(
251
- bounds: CGRect(x: 100, y: 700, width: 30, height: 30),
252
- forType: .text, withProperties: nil
253
- )
254
- note.contents = "This is a sticky note."
255
- note.color = .systemYellow
256
- note.iconType = .comment
257
- page.addAnnotation(note)
258
- ```
247
+ `document.string` is the whole document, `page.string` one page,
248
+ `page.attributedString` keeps fonts and styles, and `page.selection(for:)`
249
+ limits extraction to a rectangle. Check `pageCount > 0` before asking for
250
+ page 0.
259
251
 
260
- ### Free Text Annotation
252
+ ### Highlighting hits
261
253
 
262
254
  ```swift
263
- let freeText = PDFAnnotation(
264
- bounds: CGRect(x: 50, y: 600, width: 300, height: 40),
265
- forType: .freeText, withProperties: nil
266
- )
267
- freeText.contents = "Added commentary"
268
- freeText.font = UIFont.systemFont(ofSize: 14)
269
- freeText.fontColor = .darkGray
270
- page.addAnnotation(freeText)
255
+ import PDFKit
256
+
257
+ @MainActor
258
+ func mark(_ hits: [PDFSelection], in reader: PDFView) {
259
+ for hit in hits { hit.color = .systemOrange }
260
+ reader.highlightedSelections = hits
261
+ if let firstHit = hits.first {
262
+ reader.setCurrentSelection(firstHit, animate: true)
263
+ reader.go(to: firstHit)
264
+ }
265
+ }
271
266
  ```
272
267
 
273
- ### Link Annotation
268
+ ## Annotations
269
+
270
+ Create an annotation with `PDFAnnotation(bounds:forType:withProperties:)` and
271
+ attach it with `page.addAnnotation(_:)`.
274
272
 
275
273
  ```swift
276
- let link = PDFAnnotation(
277
- bounds: CGRect(x: 50, y: 500, width: 200, height: 20),
278
- forType: .link, withProperties: nil
279
- )
280
- link.url = URL(string: "https://example.com")
281
- page.addAnnotation(link)
282
-
283
- // Internal page link
284
- link.destination = PDFDestination(page: targetPage, at: .zero)
285
- ```
274
+ import PDFKit
275
+ import UIKit
286
276
 
287
- ### Removing Annotations
277
+ func annotate(_ page: PDFPage, hit: PDFSelection, target: PDFPage) {
278
+ let marker = PDFAnnotation(bounds: hit.bounds(for: page), forType: .highlight, withProperties: nil)
279
+ marker.color = UIColor.systemGreen.withAlphaComponent(0.5)
280
+ page.addAnnotation(marker)
281
+
282
+ let note = PDFAnnotation(bounds: CGRect(x: 40, y: 40, width: 24, height: 24), forType: .text, withProperties: nil)
283
+ note.contents = "Check this total"
284
+ note.color = .systemBlue
285
+ note.iconType = .comment
286
+ page.addAnnotation(note)
287
+
288
+ let label = PDFAnnotation(bounds: CGRect(x: 72, y: 120, width: 220, height: 30), forType: .freeText, withProperties: nil)
289
+ label.contents = "Approved"
290
+ label.font = .boldSystemFont(ofSize: 16)
291
+ label.fontColor = .systemRed
292
+ page.addAnnotation(label)
293
+
294
+ let web = PDFAnnotation(bounds: CGRect(x: 72, y: 170, width: 160, height: 20), forType: .link, withProperties: nil)
295
+ web.url = URL(string: "https://example.org/terms")
296
+ page.addAnnotation(web)
297
+
298
+ let internalJump = PDFAnnotation(bounds: CGRect(x: 72, y: 200, width: 160, height: 20), forType: .link, withProperties: nil)
299
+ internalJump.destination = PDFDestination(page: target, at: CGPoint(x: 0, y: 792))
300
+ page.addAnnotation(internalJump)
301
+ }
288
302
 
289
- ```swift
290
- for annotation in page.annotations {
291
- page.removeAnnotation(annotation)
303
+ func stripMarkup(from page: PDFPage) {
304
+ for item in page.annotations {
305
+ page.removeAnnotation(item)
306
+ }
292
307
  }
293
308
  ```
294
309
 
295
- Common subtypes include `.highlight`, `.underline`, `.strikeOut`, `.text`,
296
- `.freeText`, `.ink`, `.link`, `.line`, `.square`, `.circle`, `.stamp`, and
310
+ Commonly used subtypes: `.highlight`, `.underline`, `.strikeOut`, `.text`,
311
+ `.freeText`, `.ink`, `.link`, `.line`, `.square`, `.circle`, `.stamp`,
297
312
  `.widget`.
298
313
 
299
314
  ## Thumbnails
300
315
 
301
316
  ### PDFThumbnailView
302
317
 
303
- `PDFThumbnailView` shows a strip of page thumbnails linked to a `PDFView`.
318
+ `PDFThumbnailView` shows a strip of page previews. Point its `pdfView` at the
319
+ main viewer so taps navigate and the current page is highlighted.
304
320
 
305
321
  ```swift
306
- let thumbnailView = PDFThumbnailView()
307
- thumbnailView.pdfView = pdfView
308
- thumbnailView.thumbnailSize = CGSize(width: 60, height: 80)
309
- thumbnailView.layoutMode = .vertical
310
- thumbnailView.translatesAutoresizingMaskIntoConstraints = false
311
- view.addSubview(thumbnailView)
322
+ import PDFKit
323
+
324
+ @MainActor
325
+ func makeStrip(for reader: PDFView) -> PDFThumbnailView {
326
+ let strip = PDFThumbnailView()
327
+ strip.pdfView = reader
328
+ strip.thumbnailSize = CGSize(width: 48, height: 64)
329
+ strip.layoutMode = .vertical
330
+ return strip
331
+ }
312
332
  ```
313
333
 
314
- ### Generating Thumbnails Programmatically
334
+ ### Generating images
315
335
 
316
336
  ```swift
317
- let thumbnail = page.thumbnail(of: CGSize(width: 120, height: 160), for: .mediaBox)
337
+ import PDFKit
338
+ import UIKit
318
339
 
319
- // All pages
320
- let thumbnails = (0..<document.pageCount).compactMap {
321
- document.page(at: $0)?.thumbnail(of: CGSize(width: 120, height: 160), for: .mediaBox)
340
+ func previews(of file: PDFDocument) -> [UIImage] {
341
+ let size = CGSize(width: 120, height: 160)
342
+ let cover = file.page(at: 0)?.thumbnail(of: size, for: .mediaBox)
343
+ _ = cover
344
+ return (0..<file.pageCount).compactMap { file.page(at: $0)?.thumbnail(of: size, for: .mediaBox) }
322
345
  }
323
346
  ```
324
347
 
325
- ## SwiftUI Integration
348
+ ## SwiftUI
326
349
 
327
- Wrap `PDFView` in a `UIViewRepresentable` for SwiftUI. PDF-specific wrappers
328
- that configure `PDFView`, pages, annotations, search, thumbnails, or overlays
329
- belong in this skill; route only generic representable lifecycle, layout, or SwiftUI state architecture questions to SwiftUI/UIKit interop guidance.
350
+ Wrap `PDFView` in a `UIViewRepresentable`. Wrappers that configure the viewer,
351
+ move between pages, manage annotations, search, show thumbnails or install
352
+ overlays belong to this skill. Only generic representable questions (lifecycle,
353
+ sizing, state architecture) go to `swiftui-uikit-interop`.
330
354
 
331
355
  ```swift
332
- import SwiftUI
333
356
  import PDFKit
357
+ import SwiftUI
334
358
 
335
- struct PDFKitView: UIViewRepresentable {
359
+ struct PDFReader: UIViewRepresentable {
336
360
  let document: PDFDocument
337
361
 
338
362
  func makeUIView(context: Context) -> PDFView {
339
- let pdfView = PDFView()
340
- pdfView.autoScales = true
341
- pdfView.displayMode = .singlePageContinuous
342
- pdfView.document = document
343
- return pdfView
363
+ let reader = PDFView()
364
+ reader.autoScales = true
365
+ reader.displayMode = .singlePageContinuous
366
+ reader.document = document
367
+ return reader
344
368
  }
345
369
 
346
- func updateUIView(_ pdfView: PDFView, context: Context) {
347
- if pdfView.document !== document {
348
- pdfView.document = document
370
+ func updateUIView(_ reader: PDFView, context: Context) {
371
+ if reader.document !== document {
372
+ reader.document = document
349
373
  }
350
374
  }
351
375
  }
352
- ```
353
-
354
- ### Usage
355
376
 
356
- ```swift
357
- struct DocumentScreen: View {
358
- let url: URL
377
+ struct InvoiceScreen: View {
378
+ let fileURL: URL
359
379
 
360
380
  var body: some View {
361
- if let document = PDFDocument(url: url) {
362
- PDFKitView(document: document)
381
+ if let file = PDFDocument(url: fileURL) {
382
+ PDFReader(document: file)
363
383
  .ignoresSafeArea()
364
384
  } else {
365
- ContentUnavailableView("Unable to load PDF", systemImage: "doc.questionmark")
385
+ ContentUnavailableView("Cannot open invoice", systemImage: "doc.questionmark")
366
386
  }
367
387
  }
368
388
  }
369
389
  ```
370
390
 
371
- For interactive wrappers with page tracking, annotation hit detection, and
372
- coordinator patterns, see [references/pdfkit-patterns.md](references/pdfkit-patterns.md).
391
+ A version that binds the current page, reports annotation taps and uses a
392
+ coordinator is in [the patterns reference](references/pdfkit-patterns.md#coordinator-based-swiftui-wrapper).
373
393
 
374
- ### Page Overlays (iOS 16+)
394
+ ### Page overlays (iOS 16+)
375
395
 
376
- `PDFPageOverlayViewProvider` places UIKit views on top of individual pages
377
- for interactive controls or custom rendering beyond standard annotations.
396
+ `PDFPageOverlayViewProvider` places a UIKit view above each page, for
397
+ interactive controls or custom drawing. Implement
398
+ `pdfView(_:overlayViewFor:) -> UIView?` and assign the provider to
399
+ `pdfView.pageOverlayViewProvider`. That property is weak, so something else
400
+ must keep the provider alive.
378
401
 
379
402
  ```swift
380
- class OverlayProvider: NSObject, PDFPageOverlayViewProvider {
403
+ import PDFKit
404
+ import UIKit
405
+
406
+ @MainActor
407
+ final class StampOverlays: NSObject, @preconcurrency PDFPageOverlayViewProvider {
381
408
  func pdfView(_ view: PDFView, overlayViewFor page: PDFPage) -> UIView? {
382
- let overlay = UIView()
383
- // Add custom subviews
384
- return overlay
409
+ let badge = UILabel()
410
+ badge.text = "DRAFT"
411
+ badge.textColor = .systemRed
412
+ badge.sizeToFit()
413
+ return badge
385
414
  }
386
415
  }
387
416
 
388
- class PDFOverlayController: UIViewController {
389
- let pdfView = PDFView()
390
- private let overlayProvider = OverlayProvider()
417
+ final class DraftViewer: UIViewController {
418
+ private let reader = PDFView()
419
+ private let overlays = StampOverlays()
391
420
 
392
421
  override func viewDidLoad() {
393
422
  super.viewDidLoad()
394
- pdfView.pageOverlayViewProvider = overlayProvider
395
- }
396
- }
397
- ```
398
-
399
- `pageOverlayViewProvider` is weak, so keep the provider strongly owned. For overlay lifecycle and save handling, read [references/pdfkit-patterns.md](references/pdfkit-patterns.md).
400
-
401
- ## Common Mistakes
402
-
403
- ### DON'T: Force-unwrap PDFDocument init
404
-
405
- `PDFDocument(url:)` and `PDFDocument(data:)` are failable initializers.
406
-
407
- ```swift
408
- // WRONG
409
- let document = PDFDocument(url: url)!
410
-
411
- // CORRECT
412
- guard let document = PDFDocument(url: url) else { return }
413
- ```
414
-
415
- ### DON'T: Forget autoScales on PDFView
416
-
417
- Without `autoScales`, the PDF renders at its native resolution.
418
-
419
- ```swift
420
- // WRONG
421
- pdfView.document = document
422
-
423
- // CORRECT
424
- pdfView.autoScales = true
425
- pdfView.document = document
426
- ```
427
-
428
- ### DON'T: Ignore PDF coordinate system in annotations
429
-
430
- PDF page coordinates have origin at the bottom-left with Y increasing
431
- upward -- opposite of UIKit.
432
-
433
- ```swift
434
- // WRONG: UIKit coordinates
435
- let bounds = CGRect(x: 50, y: 50, width: 200, height: 30)
436
-
437
- // CORRECT: PDF coordinates (origin bottom-left)
438
- let pageBounds = page.bounds(for: .mediaBox)
439
- let pdfY = pageBounds.height - 50 - 30
440
- let bounds = CGRect(x: 50, y: pdfY, width: 200, height: 30)
441
- ```
442
-
443
- ### DON'T: Modify annotations on a background thread
444
-
445
- PDFKit classes are not thread-safe.
446
-
447
- ```swift
448
- // WRONG
449
- DispatchQueue.global().async { page.addAnnotation(annotation) }
450
-
451
- // CORRECT
452
- DispatchQueue.main.async { page.addAnnotation(annotation) }
453
- ```
454
-
455
- ### DON'T: Compare PDFDocument with == in UIViewRepresentable
456
-
457
- `PDFDocument` is a reference type. Use identity (`!==`).
458
-
459
- ```swift
460
- // WRONG: Always replaces document
461
- func updateUIView(_ pdfView: PDFView, context: Context) {
462
- pdfView.document = document
463
- }
464
-
465
- // CORRECT
466
- func updateUIView(_ pdfView: PDFView, context: Context) {
467
- if pdfView.document !== document {
468
- pdfView.document = document
423
+ reader.pageOverlayViewProvider = overlays
469
424
  }
470
425
  }
471
426
  ```
472
427
 
473
- ## Review Checklist
474
-
475
- - [ ] `PDFDocument` init uses optional binding, not force-unwrap
476
- - [ ] `pdfView.autoScales = true` set for proper initial display
477
- - [ ] Page indices checked against `pageCount` before access
478
- - [ ] `displayMode` and `displayDirection` configured to match design
479
- - [ ] Annotations use PDF coordinate space (origin bottom-left, Y up)
480
- - [ ] All PDFKit mutations happen on the main thread
481
- - [ ] Password-protected PDFs handled with `isLocked` / `unlock(withPassword:)`
482
- - [ ] SwiftUI wrapper uses `!==` identity check in `updateUIView`
483
- - [ ] `PDFViewPageChanged` notification observed for page tracking
484
- - [ ] `PDFThumbnailView.pdfView` linked to the main `PDFView`
485
- - [ ] Large-document search uses async `beginFindString` with delegate
486
- - [ ] Saved documents use `write(to:withOptions:)` when encryption needed
428
+ ## Common mistakes
429
+
430
+ - **Force-unwrapping the initializers.** `PDFDocument(url:)` and
431
+ `PDFDocument(data:)` return `nil` for a bad file. Use `guard let`.
432
+ - **Forgetting `autoScales`.** Without it, pages appear at their native size.
433
+ - **Using UIKit coordinates on a page.** PDF space starts at the bottom-left and
434
+ y grows upward. To place something at a UIKit-style top offset, compute
435
+ `page.bounds(for: .mediaBox).height - topOffset - itemHeight`.
436
+ - **Mutating from a background queue.** PDFKit classes are not thread-safe.
437
+ Add or change annotations on the main thread.
438
+ - **Reassigning the document in `updateUIView`.** `PDFDocument` is a class;
439
+ compare with `!==` first, otherwise every SwiftUI update reloads the file.
440
+
441
+ ## Review checklist
442
+
443
+ - [ ] `PDFDocument` is created with optional binding
444
+ - [ ] `autoScales = true` is set
445
+ - [ ] Every page index is checked against `pageCount`
446
+ - [ ] `displayMode` and `displayDirection` match the design
447
+ - [ ] Annotation rectangles are in PDF coordinate space
448
+ - [ ] All PDFKit mutation happens on the main thread
449
+ - [ ] Locked files go through `isLocked` and `unlock(withPassword:)`
450
+ - [ ] The SwiftUI wrapper compares documents with `!==` in `updateUIView`
451
+ - [ ] `PDFViewPageChanged` drives any page indicator
452
+ - [ ] `PDFThumbnailView.pdfView` points at the main `PDFView`
453
+ - [ ] Long documents are searched with `beginFindString` and the delegate
454
+ - [ ] `write(to:withOptions:)` is used when the file must be encrypted
487
455
 
488
456
  ## References
489
457
 
490
- - Extended patterns (forms, watermarks, merging, printing, overlays, outlines, custom drawing): [references/pdfkit-patterns.md](references/pdfkit-patterns.md)
491
- - [PDFKit framework](https://sosumi.ai/documentation/pdfkit)
492
- - [PDFView](https://sosumi.ai/documentation/pdfkit/pdfview)
493
- - [PDFDocument](https://sosumi.ai/documentation/pdfkit/pdfdocument)
494
- - [PDFPage](https://sosumi.ai/documentation/pdfkit/pdfpage)
495
- - [PDFAnnotation](https://sosumi.ai/documentation/pdfkit/pdfannotation)
496
- - [PDFSelection](https://sosumi.ai/documentation/pdfkit/pdfselection)
497
- - [PDFThumbnailView](https://sosumi.ai/documentation/pdfkit/pdfthumbnailview)
498
- - [PDFPageOverlayViewProvider](https://sosumi.ai/documentation/pdfkit/pdfpageoverlayviewprovider)
499
- - [Adding Widgets to a PDF Document](https://sosumi.ai/documentation/pdfkit/adding-widgets-to-a-pdf-document)
500
- - [Adding Custom Graphics to a PDF](https://sosumi.ai/documentation/pdfkit/adding-custom-graphics-to-a-pdf)
458
+ - [PDFKit patterns](references/pdfkit-patterns.md) - forms, building PDFs, watermarks, merging and splitting, printing, outlines, custom annotation and page classes, overlay lifecycle, rendering, rotation and crop, burn-in, permissions, coordinator wrapper
459
+ - [PDFKit](https://developer.apple.com/documentation/pdfkit)
460
+ - [PDFView](https://developer.apple.com/documentation/pdfkit/pdfview)
461
+ - [PDFDocument](https://developer.apple.com/documentation/pdfkit/pdfdocument)
462
+ - [PDFPage](https://developer.apple.com/documentation/pdfkit/pdfpage)
463
+ - [PDFAnnotation](https://developer.apple.com/documentation/pdfkit/pdfannotation)
464
+ - [PDFSelection](https://developer.apple.com/documentation/pdfkit/pdfselection)
465
+ - [PDFThumbnailView](https://developer.apple.com/documentation/pdfkit/pdfthumbnailview)
466
+ - [PDFPageOverlayViewProvider](https://developer.apple.com/documentation/pdfkit/pdfpageoverlayviewprovider)
467
+ - [Adding widgets to a PDF document](https://developer.apple.com/documentation/pdfkit/adding-widgets-to-a-pdf-document)
468
+ - [Adding custom graphics to a PDF](https://developer.apple.com/documentation/pdfkit/adding-custom-graphics-to-a-pdf)