buildanything 1.7.0 → 1.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 (222) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +55 -0
  4. package/README.md +71 -61
  5. package/agents/ios-app-review-guardian.md +49 -0
  6. package/agents/ios-foundation-models-specialist.md +46 -0
  7. package/agents/ios-storekit-specialist.md +52 -0
  8. package/agents/ios-swift-architect.md +102 -0
  9. package/agents/ios-swift-search.md +130 -0
  10. package/agents/ios-swift-ui-design.md +104 -0
  11. package/commands/build.md +80 -176
  12. package/commands/fix.md +65 -0
  13. package/commands/setup.md +73 -0
  14. package/commands/ux-review.md +63 -0
  15. package/commands/verify.md +72 -0
  16. package/hooks/session-start +18 -1
  17. package/package.json +5 -2
  18. package/protocols/brainstorm.md +99 -0
  19. package/protocols/build-fix.md +52 -0
  20. package/protocols/cleanup.md +54 -0
  21. package/protocols/design.md +269 -0
  22. package/protocols/eval-harness.md +61 -0
  23. package/protocols/fake-data-detector.md +64 -0
  24. package/protocols/ios-context.md +235 -0
  25. package/protocols/ios-frameworks-map.md +323 -0
  26. package/protocols/ios-phase-branches.md +162 -0
  27. package/protocols/ios-preflight.md +27 -0
  28. package/protocols/metric-loop.md +93 -0
  29. package/protocols/planning.md +87 -0
  30. package/protocols/smoke-test.md +110 -0
  31. package/protocols/verify.md +67 -0
  32. package/protocols/web-phase-branches.md +201 -0
  33. package/skills/ios/_VENDORED.md +60 -0
  34. package/skills/ios/activitykit/LICENSE +131 -0
  35. package/skills/ios/activitykit/SKILL.md +505 -0
  36. package/skills/ios/activitykit/references/activitykit-patterns.md +868 -0
  37. package/skills/ios/app-intents/LICENSE +131 -0
  38. package/skills/ios/app-intents/SKILL.md +494 -0
  39. package/skills/ios/app-intents/references/appintents-advanced.md +1076 -0
  40. package/skills/ios/apple-on-device-ai/LICENSE +131 -0
  41. package/skills/ios/apple-on-device-ai/SKILL.md +505 -0
  42. package/skills/ios/apple-on-device-ai/references/coreml-conversion.md +425 -0
  43. package/skills/ios/apple-on-device-ai/references/coreml-optimization.md +344 -0
  44. package/skills/ios/apple-on-device-ai/references/foundation-models.md +508 -0
  45. package/skills/ios/apple-on-device-ai/references/mlx-swift.md +285 -0
  46. package/skills/ios/ios-26-platform/SKILL.md +53 -0
  47. package/skills/ios/ios-26-platform/references/automatic-adoption.md +161 -0
  48. package/skills/ios/ios-26-platform/references/backward-compat.md +238 -0
  49. package/skills/ios/ios-26-platform/references/liquid-glass.md +255 -0
  50. package/skills/ios/ios-26-platform/references/swiftui-apis.md +277 -0
  51. package/skills/ios/ios-26-platform/references/toolbar-navigation.md +250 -0
  52. package/skills/ios/ios-bootstrap/SKILL.md +98 -0
  53. package/skills/ios/ios-bootstrap/references/apple-docs-mcp-config.md +28 -0
  54. package/skills/ios/ios-bootstrap/references/new-project-dialog.md +41 -0
  55. package/skills/ios/ios-bootstrap/references/xcode-mcp-config.md +29 -0
  56. package/skills/ios/ios-debugger-agent/LICENSE +21 -0
  57. package/skills/ios/ios-debugger-agent/SKILL.md +58 -0
  58. package/skills/ios/ios-debugger-agent/agents/openai.yaml +4 -0
  59. package/skills/ios/ios-entitlements-generator/SKILL.md +47 -0
  60. package/skills/ios/ios-hig/SKILL.md +41 -0
  61. package/skills/ios/ios-hig/references/accessibility.md +81 -0
  62. package/skills/ios/ios-hig/references/content.md +142 -0
  63. package/skills/ios/ios-hig/references/feedback.md +123 -0
  64. package/skills/ios/ios-hig/references/interaction.md +199 -0
  65. package/skills/ios/ios-hig/references/performance-platform.md +129 -0
  66. package/skills/ios/ios-hig/references/privacy-permissions.md +181 -0
  67. package/skills/ios/ios-hig/references/visual-design.md +84 -0
  68. package/skills/ios/ios-info-plist-hardening/SKILL.md +130 -0
  69. package/skills/ios/ios-maestro-flow-author/SKILL.md +68 -0
  70. package/skills/ios/ios-maestro-flow-author/references/input-and-scroll.yaml +17 -0
  71. package/skills/ios/ios-maestro-flow-author/references/modal-and-dismiss.yaml +14 -0
  72. package/skills/ios/ios-maestro-flow-author/references/onboarding-flow.yaml +16 -0
  73. package/skills/ios/ios-maestro-flow-author/references/tab-navigation.yaml +13 -0
  74. package/skills/ios/ios-maestro-flow-author/references/tap-and-assert.yaml +9 -0
  75. package/skills/ios/swift-accessibility/LICENSE +21 -0
  76. package/skills/ios/swift-accessibility/SKILL.md +371 -0
  77. package/skills/ios/swift-accessibility/examples/before-after-appkit.md +446 -0
  78. package/skills/ios/swift-accessibility/examples/before-after-swiftui.md +441 -0
  79. package/skills/ios/swift-accessibility/examples/before-after-uikit.md +464 -0
  80. package/skills/ios/swift-accessibility/references/assistive-access.md +441 -0
  81. package/skills/ios/swift-accessibility/references/display-settings.md +491 -0
  82. package/skills/ios/swift-accessibility/references/dynamic-type.md +420 -0
  83. package/skills/ios/swift-accessibility/references/media-accessibility.md +421 -0
  84. package/skills/ios/swift-accessibility/references/motor-input.md +393 -0
  85. package/skills/ios/swift-accessibility/references/nutrition-labels.md +362 -0
  86. package/skills/ios/swift-accessibility/references/platform-specifics.md +515 -0
  87. package/skills/ios/swift-accessibility/references/semantic-structure.md +585 -0
  88. package/skills/ios/swift-accessibility/references/testing-auditing.md +507 -0
  89. package/skills/ios/swift-accessibility/references/voice-control.md +317 -0
  90. package/skills/ios/swift-accessibility/references/voiceover-swiftui.md +584 -0
  91. package/skills/ios/swift-accessibility/references/voiceover-uikit.md +519 -0
  92. package/skills/ios/swift-accessibility/references/wcag-mapping.md +167 -0
  93. package/skills/ios/swift-accessibility/resources/audit-template.swift +128 -0
  94. package/skills/ios/swift-accessibility/resources/qa-checklist.md +258 -0
  95. package/skills/ios/swift-concurrency/LICENSE +21 -0
  96. package/skills/ios/swift-concurrency/SKILL.md +171 -0
  97. package/skills/ios/swift-concurrency/references/_index.md +50 -0
  98. package/skills/ios/swift-concurrency/references/actors.md +660 -0
  99. package/skills/ios/swift-concurrency/references/async-algorithms.md +847 -0
  100. package/skills/ios/swift-concurrency/references/async-await-basics.md +266 -0
  101. package/skills/ios/swift-concurrency/references/async-sequences.md +710 -0
  102. package/skills/ios/swift-concurrency/references/core-data.md +560 -0
  103. package/skills/ios/swift-concurrency/references/glossary.md +135 -0
  104. package/skills/ios/swift-concurrency/references/linting.md +155 -0
  105. package/skills/ios/swift-concurrency/references/memory-management.md +569 -0
  106. package/skills/ios/swift-concurrency/references/migration.md +1104 -0
  107. package/skills/ios/swift-concurrency/references/performance.md +593 -0
  108. package/skills/ios/swift-concurrency/references/sendable.md +598 -0
  109. package/skills/ios/swift-concurrency/references/tasks.md +636 -0
  110. package/skills/ios/swift-concurrency/references/testing.md +592 -0
  111. package/skills/ios/swift-concurrency/references/threading.md +495 -0
  112. package/skills/ios/swift-security-expert/LICENSE +21 -0
  113. package/skills/ios/swift-security-expert/SKILL.md +470 -0
  114. package/skills/ios/swift-security-expert/references/biometric-authentication.md +565 -0
  115. package/skills/ios/swift-security-expert/references/certificate-trust.md +592 -0
  116. package/skills/ios/swift-security-expert/references/common-anti-patterns.md +690 -0
  117. package/skills/ios/swift-security-expert/references/compliance-owasp-mapping.md +537 -0
  118. package/skills/ios/swift-security-expert/references/credential-storage-patterns.md +721 -0
  119. package/skills/ios/swift-security-expert/references/cryptokit-public-key.md +505 -0
  120. package/skills/ios/swift-security-expert/references/cryptokit-symmetric.md +497 -0
  121. package/skills/ios/swift-security-expert/references/keychain-access-control.md +508 -0
  122. package/skills/ios/swift-security-expert/references/keychain-fundamentals.md +596 -0
  123. package/skills/ios/swift-security-expert/references/keychain-item-classes.md +476 -0
  124. package/skills/ios/swift-security-expert/references/keychain-sharing.md +458 -0
  125. package/skills/ios/swift-security-expert/references/migration-legacy-stores.md +727 -0
  126. package/skills/ios/swift-security-expert/references/secure-enclave.md +539 -0
  127. package/skills/ios/swift-security-expert/references/testing-security-code.md +781 -0
  128. package/skills/ios/swift-testing-expert/LICENSE +21 -0
  129. package/skills/ios/swift-testing-expert/SKILL.md +79 -0
  130. package/skills/ios/swift-testing-expert/references/_index.md +12 -0
  131. package/skills/ios/swift-testing-expert/references/async-testing-and-waiting.md +127 -0
  132. package/skills/ios/swift-testing-expert/references/expectations.md +145 -0
  133. package/skills/ios/swift-testing-expert/references/fundamentals.md +141 -0
  134. package/skills/ios/swift-testing-expert/references/migration-from-xctest.md +127 -0
  135. package/skills/ios/swift-testing-expert/references/parallelization-and-isolation.md +95 -0
  136. package/skills/ios/swift-testing-expert/references/parameterized-testing.md +284 -0
  137. package/skills/ios/swift-testing-expert/references/performance-and-best-practices.md +187 -0
  138. package/skills/ios/swift-testing-expert/references/traits-and-tags.md +114 -0
  139. package/skills/ios/swift-testing-expert/references/xcode-workflows.md +70 -0
  140. package/skills/ios/swiftdata-pro/LICENSE +21 -0
  141. package/skills/ios/swiftdata-pro/SKILL.md +102 -0
  142. package/skills/ios/swiftdata-pro/agents/openai.yaml +10 -0
  143. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.png +0 -0
  144. package/skills/ios/swiftdata-pro/assets/swiftdata-pro-icon.svg +29 -0
  145. package/skills/ios/swiftdata-pro/references/class-inheritance.md +104 -0
  146. package/skills/ios/swiftdata-pro/references/cloudkit.md +10 -0
  147. package/skills/ios/swiftdata-pro/references/core-rules.md +20 -0
  148. package/skills/ios/swiftdata-pro/references/indexing.md +27 -0
  149. package/skills/ios/swiftdata-pro/references/predicates.md +73 -0
  150. package/skills/ios/swiftui-design-principles/AGENTS.md +21 -0
  151. package/skills/ios/swiftui-design-principles/LICENSE +21 -0
  152. package/skills/ios/swiftui-design-principles/README.md +41 -0
  153. package/skills/ios/swiftui-design-principles/SKILL.md +605 -0
  154. package/skills/ios/swiftui-design-principles/metadata.json +10 -0
  155. package/skills/ios/swiftui-liquid-glass/LICENSE +21 -0
  156. package/skills/ios/swiftui-liquid-glass/SKILL.md +95 -0
  157. package/skills/ios/swiftui-liquid-glass/agents/openai.yaml +4 -0
  158. package/skills/ios/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  159. package/skills/ios/swiftui-performance-audit/LICENSE +21 -0
  160. package/skills/ios/swiftui-performance-audit/SKILL.md +111 -0
  161. package/skills/ios/swiftui-performance-audit/agents/openai.yaml +4 -0
  162. package/skills/ios/swiftui-performance-audit/references/code-smells.md +150 -0
  163. package/skills/ios/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  164. package/skills/ios/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  165. package/skills/ios/swiftui-performance-audit/references/profiling-intake.md +44 -0
  166. package/skills/ios/swiftui-performance-audit/references/report-template.md +47 -0
  167. package/skills/ios/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  168. package/skills/ios/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  169. package/skills/ios/swiftui-pro/LICENSE +21 -0
  170. package/skills/ios/swiftui-pro/SKILL.md +108 -0
  171. package/skills/ios/swiftui-pro/agents/openai.yaml +10 -0
  172. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  173. package/skills/ios/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  174. package/skills/ios/swiftui-pro/references/accessibility.md +13 -0
  175. package/skills/ios/swiftui-pro/references/api.md +39 -0
  176. package/skills/ios/swiftui-pro/references/data.md +43 -0
  177. package/skills/ios/swiftui-pro/references/design.md +31 -0
  178. package/skills/ios/swiftui-pro/references/hygiene.md +9 -0
  179. package/skills/ios/swiftui-pro/references/navigation.md +14 -0
  180. package/skills/ios/swiftui-pro/references/performance.md +46 -0
  181. package/skills/ios/swiftui-pro/references/swift.md +56 -0
  182. package/skills/ios/swiftui-pro/references/views.md +35 -0
  183. package/skills/ios/swiftui-ui-patterns/LICENSE +21 -0
  184. package/skills/ios/swiftui-ui-patterns/SKILL.md +100 -0
  185. package/skills/ios/swiftui-ui-patterns/agents/openai.yaml +4 -0
  186. package/skills/ios/swiftui-ui-patterns/references/app-wiring.md +201 -0
  187. package/skills/ios/swiftui-ui-patterns/references/async-state.md +96 -0
  188. package/skills/ios/swiftui-ui-patterns/references/components-index.md +50 -0
  189. package/skills/ios/swiftui-ui-patterns/references/controls.md +57 -0
  190. package/skills/ios/swiftui-ui-patterns/references/deeplinks.md +66 -0
  191. package/skills/ios/swiftui-ui-patterns/references/focus.md +90 -0
  192. package/skills/ios/swiftui-ui-patterns/references/form.md +97 -0
  193. package/skills/ios/swiftui-ui-patterns/references/grids.md +71 -0
  194. package/skills/ios/swiftui-ui-patterns/references/haptics.md +71 -0
  195. package/skills/ios/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  196. package/skills/ios/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  197. package/skills/ios/swiftui-ui-patterns/references/list.md +86 -0
  198. package/skills/ios/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  199. package/skills/ios/swiftui-ui-patterns/references/macos-settings.md +71 -0
  200. package/skills/ios/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  201. package/skills/ios/swiftui-ui-patterns/references/media.md +73 -0
  202. package/skills/ios/swiftui-ui-patterns/references/menu-bar.md +101 -0
  203. package/skills/ios/swiftui-ui-patterns/references/navigationstack.md +159 -0
  204. package/skills/ios/swiftui-ui-patterns/references/overlay.md +45 -0
  205. package/skills/ios/swiftui-ui-patterns/references/performance.md +62 -0
  206. package/skills/ios/swiftui-ui-patterns/references/previews.md +48 -0
  207. package/skills/ios/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  208. package/skills/ios/swiftui-ui-patterns/references/scrollview.md +87 -0
  209. package/skills/ios/swiftui-ui-patterns/references/searchable.md +71 -0
  210. package/skills/ios/swiftui-ui-patterns/references/sheets.md +155 -0
  211. package/skills/ios/swiftui-ui-patterns/references/split-views.md +72 -0
  212. package/skills/ios/swiftui-ui-patterns/references/tabview.md +114 -0
  213. package/skills/ios/swiftui-ui-patterns/references/theming.md +71 -0
  214. package/skills/ios/swiftui-ui-patterns/references/title-menus.md +93 -0
  215. package/skills/ios/swiftui-ui-patterns/references/top-bar.md +49 -0
  216. package/skills/ios/swiftui-view-refactor/LICENSE +21 -0
  217. package/skills/ios/swiftui-view-refactor/SKILL.md +207 -0
  218. package/skills/ios/swiftui-view-refactor/agents/openai.yaml +4 -0
  219. package/skills/ios/swiftui-view-refactor/references/mv-patterns.md +161 -0
  220. package/skills/ios/widgetkit/LICENSE +131 -0
  221. package/skills/ios/widgetkit/SKILL.md +502 -0
  222. package/skills/ios/widgetkit/references/widgetkit-advanced.md +871 -0
@@ -0,0 +1,710 @@
1
+ # Async Sequences and Streams
2
+
3
+ Use this when:
4
+
5
+ - You need to iterate over values that arrive over time.
6
+ - You are bridging callback-based or delegate-based APIs to async/await.
7
+ - You need to choose between `AsyncSequence`, `AsyncStream`, or a regular async method.
8
+
9
+ Skip this file if:
10
+
11
+ - You need time-based operators like debounce, throttle, or merge. Use `async-algorithms.md`.
12
+ - You are choosing between `Task`, `async let`, or task groups. Use `tasks.md`.
13
+
14
+ Jump to:
15
+
16
+ - AsyncSequence Protocol
17
+ - AsyncStream / AsyncThrowingStream
18
+ - Bridging Callbacks and Delegates
19
+ - Stream Lifecycle and Cleanup
20
+ - Buffer Policies
21
+ - Standard Library Integration
22
+ - Limitations
23
+ - When to Use AsyncAlgorithms
24
+
25
+ ## AsyncSequence
26
+
27
+ Protocol for asynchronous iteration over values that become available over time.
28
+
29
+ ### Basic usage
30
+
31
+ ```swift
32
+ for await value in someAsyncSequence {
33
+ print(value)
34
+ }
35
+ ```
36
+
37
+ **Key difference from Sequence**: Values may not all be available immediately.
38
+
39
+ ### Custom implementation
40
+
41
+ ```swift
42
+ struct Counter: AsyncSequence, AsyncIteratorProtocol {
43
+ typealias Element = Int
44
+
45
+ let limit: Int
46
+ var current = 1
47
+
48
+ mutating func next() async -> Int? {
49
+ guard !Task.isCancelled else { return nil }
50
+ guard current <= limit else { return nil }
51
+
52
+ let result = current
53
+ current += 1
54
+ return result
55
+ }
56
+
57
+ func makeAsyncIterator() -> Counter {
58
+ self
59
+ }
60
+ }
61
+
62
+ // Usage
63
+ for await count in Counter(limit: 5) {
64
+ print(count) // 1, 2, 3, 4, 5
65
+ }
66
+ ```
67
+
68
+ ### Standard operators
69
+
70
+ Same functional operators as regular sequences:
71
+
72
+ ```swift
73
+ // Filter
74
+ for await even in Counter(limit: 5).filter({ $0 % 2 == 0 }) {
75
+ print(even) // 2, 4
76
+ }
77
+
78
+ // Map
79
+ let mapped = Counter(limit: 5).map { $0 % 2 == 0 ? "Even" : "Odd" }
80
+ for await label in mapped {
81
+ print(label)
82
+ }
83
+
84
+ // Contains (awaits until found or sequence ends)
85
+ let contains = await Counter(limit: 5).contains(3) // true
86
+ ```
87
+
88
+ ### Termination
89
+
90
+ Return `nil` from `next()` to end iteration:
91
+
92
+ ```swift
93
+ mutating func next() async -> Int? {
94
+ guard !Task.isCancelled else {
95
+ return nil // Stop on cancellation
96
+ }
97
+
98
+ guard current <= limit else {
99
+ return nil // Stop at limit
100
+ }
101
+
102
+ return current
103
+ }
104
+ ```
105
+
106
+ > **Course Deep Dive**: This topic is covered in detail in [Lesson 6.1: Working with asynchronous sequences](https://www.swiftconcurrencycourse.com?utm_source=github&utm_medium=agent-skill&utm_campaign=lesson-reference)
107
+
108
+ ## AsyncStream
109
+
110
+ Convenient way to create async sequences without implementing protocols.
111
+
112
+ ### Basic creation
113
+
114
+ ```swift
115
+ let stream = AsyncStream<Int> { continuation in
116
+ for i in 1...5 {
117
+ continuation.yield(i)
118
+ }
119
+ continuation.finish()
120
+ }
121
+
122
+ for await value in stream {
123
+ print(value)
124
+ }
125
+ ```
126
+
127
+ ### AsyncThrowingStream
128
+
129
+ For streams that can fail:
130
+
131
+ ```swift
132
+ let throwingStream = AsyncThrowingStream<Int, Error> { continuation in
133
+ continuation.yield(1)
134
+ continuation.yield(2)
135
+ continuation.finish(throwing: SomeError())
136
+ }
137
+
138
+ do {
139
+ for try await value in throwingStream {
140
+ print(value)
141
+ }
142
+ } catch {
143
+ print("Error: \(error)")
144
+ }
145
+ ```
146
+
147
+ > **Course Deep Dive**: This topic is covered in detail in [Lesson 6.2: Using AsyncStream and AsyncThrowingStream in your code](https://www.swiftconcurrencycourse.com?utm_source=github&utm_medium=agent-skill&utm_campaign=lesson-reference)
148
+
149
+ ## Bridging Closures to Streams
150
+
151
+ ### Progress + completion handlers
152
+
153
+ ```swift
154
+ // Old closure-based API
155
+ struct FileDownloader {
156
+ enum Status {
157
+ case downloading(Float)
158
+ case finished(Data)
159
+ }
160
+
161
+ func download(
162
+ _ url: URL,
163
+ progressHandler: @escaping (Float) -> Void,
164
+ completion: @escaping (Result<Data, Error>) -> Void
165
+ ) throws {
166
+ // Implementation
167
+ }
168
+ }
169
+
170
+ // Modern stream-based API
171
+ extension FileDownloader {
172
+ func download(_ url: URL) -> AsyncThrowingStream<Status, Error> {
173
+ AsyncThrowingStream { continuation in
174
+ do {
175
+ try self.download(url, progressHandler: { progress in
176
+ continuation.yield(.downloading(progress))
177
+ }, completion: { result in
178
+ switch result {
179
+ case .success(let data):
180
+ continuation.yield(.finished(data))
181
+ continuation.finish()
182
+ case .failure(let error):
183
+ continuation.finish(throwing: error)
184
+ }
185
+ })
186
+ } catch {
187
+ continuation.finish(throwing: error)
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ // Usage
194
+ for try await status in downloader.download(url) {
195
+ switch status {
196
+ case .downloading(let progress):
197
+ print("Progress: \(progress)")
198
+ case .finished(let data):
199
+ print("Done: \(data.count) bytes")
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Simplified with Result
205
+
206
+ ```swift
207
+ AsyncThrowingStream { continuation in
208
+ try self.download(url, progressHandler: { progress in
209
+ continuation.yield(.downloading(progress))
210
+ }, completion: { result in
211
+ continuation.yield(with: result.map { .finished($0) })
212
+ continuation.finish()
213
+ })
214
+ }
215
+ ```
216
+
217
+ ## Bridging Delegates
218
+
219
+ ### Location updates example
220
+
221
+ ```swift
222
+ final class LocationMonitor: NSObject {
223
+ private var continuation: AsyncThrowingStream<CLLocation, Error>.Continuation?
224
+ let stream: AsyncThrowingStream<CLLocation, Error>
225
+
226
+ override init() {
227
+ var capturedContinuation: AsyncThrowingStream<CLLocation, Error>.Continuation?
228
+ stream = AsyncThrowingStream { continuation in
229
+ capturedContinuation = continuation
230
+ }
231
+ super.init()
232
+ self.continuation = capturedContinuation
233
+
234
+ locationManager.delegate = self
235
+ locationManager.startUpdatingLocation()
236
+ }
237
+ }
238
+
239
+ extension LocationMonitor: CLLocationManagerDelegate {
240
+ func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
241
+ for location in locations {
242
+ continuation?.yield(location)
243
+ }
244
+ }
245
+
246
+ func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
247
+ continuation?.finish(throwing: error)
248
+ }
249
+ }
250
+
251
+ // Usage
252
+ let monitor = LocationMonitor()
253
+ for try await location in monitor.stream {
254
+ print("Location: \(location.coordinate)")
255
+ }
256
+ ```
257
+
258
+ ## Stream Lifecycle
259
+
260
+ ### Termination callback
261
+
262
+ ```swift
263
+ AsyncThrowingStream<Int, Error> { continuation in
264
+ continuation.onTermination = { @Sendable reason in
265
+ print("Terminated: \(reason)")
266
+ // Cleanup: remove observers, cancel work, etc.
267
+ }
268
+
269
+ continuation.yield(1)
270
+ continuation.finish()
271
+ }
272
+ ```
273
+
274
+ **Termination reasons**:
275
+ - `.finished` - Normal completion
276
+ - `.finished(Error?)` - Completed with error (throwing stream)
277
+ - `.cancelled` - Task canceled
278
+
279
+ ### Cancellation
280
+
281
+ Streams cancel when:
282
+ - Enclosing task cancels
283
+ - Stream goes out of scope
284
+
285
+ ```swift
286
+ let task = Task {
287
+ for try await status in download(url) {
288
+ print(status)
289
+ }
290
+ }
291
+
292
+ task.cancel() // Triggers onTermination with .cancelled
293
+ ```
294
+
295
+ **No explicit cancel method** - rely on task cancellation.
296
+
297
+ ## Buffer Policies
298
+
299
+ Control what happens to values when no one is awaiting:
300
+
301
+ ### .unbounded (default)
302
+
303
+ Buffers all values until consumed:
304
+
305
+ ```swift
306
+ let stream = AsyncStream<Int> { continuation in
307
+ (0...5).forEach { continuation.yield($0) }
308
+ continuation.finish()
309
+ }
310
+
311
+ try await Task.sleep(for: .seconds(1))
312
+
313
+ for await value in stream {
314
+ print(value) // Prints all: 0, 1, 2, 3, 4, 5
315
+ }
316
+ ```
317
+
318
+ ### .bufferingNewest(n)
319
+
320
+ Keeps only the newest N values:
321
+
322
+ ```swift
323
+ let stream = AsyncStream(bufferingPolicy: .bufferingNewest(1)) { continuation in
324
+ (0...5).forEach { continuation.yield($0) }
325
+ continuation.finish()
326
+ }
327
+
328
+ try await Task.sleep(for: .seconds(1))
329
+
330
+ for await value in stream {
331
+ print(value) // Prints only: 5
332
+ }
333
+ ```
334
+
335
+ ### .bufferingOldest(n)
336
+
337
+ Keeps only the oldest N values:
338
+
339
+ ```swift
340
+ let stream = AsyncStream(bufferingPolicy: .bufferingOldest(1)) { continuation in
341
+ (0...5).forEach { continuation.yield($0) }
342
+ continuation.finish()
343
+ }
344
+
345
+ try await Task.sleep(for: .seconds(1))
346
+
347
+ for await value in stream {
348
+ print(value) // Prints only: 0
349
+ }
350
+ ```
351
+
352
+ ### .bufferingNewest(0)
353
+
354
+ Only receives values emitted after iteration starts:
355
+
356
+ ```swift
357
+ let stream = AsyncStream(bufferingPolicy: .bufferingNewest(0)) { continuation in
358
+ continuation.yield(1) // Discarded
359
+
360
+ Task {
361
+ try await Task.sleep(for: .seconds(2))
362
+ continuation.yield(2) // Received
363
+ continuation.finish()
364
+ }
365
+ }
366
+
367
+ try await Task.sleep(for: .seconds(1))
368
+
369
+ for await value in stream {
370
+ print(value) // Prints only: 2
371
+ }
372
+ ```
373
+
374
+ **Use case**: Location updates, file system changes - only care about latest.
375
+
376
+ ## Repeated Async Calls
377
+
378
+ Use `init(unfolding:onCancel:)` for polling:
379
+
380
+ ```swift
381
+ struct PingService {
382
+ func startPinging() -> AsyncStream<Bool> {
383
+ AsyncStream {
384
+ try? await Task.sleep(for: .seconds(5))
385
+ return await ping()
386
+ } onCancel: {
387
+ print("Pinging cancelled")
388
+ }
389
+ }
390
+
391
+ func ping() async -> Bool {
392
+ // Network request
393
+ return true
394
+ }
395
+ }
396
+
397
+ // Usage
398
+ for await result in pingService.startPinging() {
399
+ print("Ping: \(result)")
400
+ }
401
+ ```
402
+
403
+ ## Standard Library Integration
404
+
405
+ ### NotificationCenter
406
+
407
+ ```swift
408
+ let stream = NotificationCenter.default.notifications(
409
+ named: .NSSystemTimeZoneDidChange
410
+ )
411
+
412
+ for await notification in stream {
413
+ print("Time zone changed")
414
+ }
415
+ ```
416
+
417
+ ### Combine publishers
418
+
419
+ ```swift
420
+ let numbers = [1, 2, 3, 4, 5]
421
+ let filtered = numbers.publisher.filter { $0 % 2 == 0 }
422
+
423
+ for await number in filtered.values {
424
+ print(number) // 2, 4
425
+ }
426
+ ```
427
+
428
+ ### Task groups
429
+
430
+ ```swift
431
+ await withTaskGroup(of: Image.self) { group in
432
+ for url in urls {
433
+ group.addTask { await download(url) }
434
+ }
435
+
436
+ for await image in group {
437
+ display(image)
438
+ }
439
+ }
440
+ ```
441
+
442
+ ## Limitations
443
+
444
+ ### Single consumer only
445
+
446
+ Unlike Combine, streams support one consumer at a time:
447
+
448
+ ```swift
449
+ let stream = AsyncStream { continuation in
450
+ (0...5).forEach { continuation.yield($0) }
451
+ continuation.finish()
452
+ }
453
+
454
+ Task {
455
+ for await value in stream {
456
+ print("Consumer 1: \(value)")
457
+ }
458
+ }
459
+
460
+ Task {
461
+ for await value in stream {
462
+ print("Consumer 2: \(value)")
463
+ }
464
+ }
465
+
466
+ // Unpredictable output - values split between consumers
467
+ // Consumer 1: 0
468
+ // Consumer 2: 1
469
+ // Consumer 1: 2
470
+ // Consumer 2: 3
471
+ ```
472
+
473
+ **Solution**: Create separate streams or use third-party libraries (AsyncExtensions).
474
+
475
+ ### No values after termination
476
+
477
+ Once finished, stream won't emit new values:
478
+
479
+ ```swift
480
+ let stream = AsyncStream<Int> { continuation in
481
+ continuation.finish() // Terminate immediately
482
+ continuation.yield(1) // Never received
483
+ }
484
+
485
+ for await value in stream {
486
+ print(value) // Loop exits immediately
487
+ }
488
+ ```
489
+
490
+ ## Decision Guide
491
+
492
+ ### Use AsyncSequence when:
493
+
494
+ - Implementing standard library-style protocols
495
+ - Need fine-grained control over iteration
496
+ - Building reusable sequence types
497
+ - Working with existing sequence protocols
498
+
499
+ **Reality**: Rarely needed in application code.
500
+
501
+ ### Use AsyncStream when:
502
+
503
+ - Bridging delegates to async/await
504
+ - Converting closure-based APIs
505
+ - Emitting events manually
506
+ - Polling or repeated async operations
507
+ - Most common use case
508
+
509
+ ---
510
+
511
+ ## When to Use AsyncAlgorithms vs Standard Library
512
+
513
+ ### Use AsyncAlgorithms when:
514
+
515
+ - **Time-based operations** need debounce/throttle/timer
516
+ - **Combining multiple async sequences** (merge, combineLatest, zip)
517
+ - **Multi-consumer scenarios** require backpressure (AsyncChannel)
518
+ - **Complex operator chains** that Combine would handle naturally
519
+ - **Need specific operators** not in standard library
520
+
521
+ ### Use Standard Library when:
522
+
523
+ - **Bridging callback APIs** → AsyncStream
524
+ - **Simple iteration** → for await in sequence
525
+ - **Single-value operations** → async/await
526
+ - **Basic transformations** → map/filter/contains
527
+
528
+ ### Quick Decision Table
529
+
530
+ | Need | Solution |
531
+ |------|----------|
532
+ | Debounce search input | ✅ AsyncAlgorithms.debounce() |
533
+ | Throttle button clicks | ✅ AsyncAlgorithms.throttle() |
534
+ | Merge independent streams | ✅ AsyncAlgorithms.merge() |
535
+ | Combine dependent values | ✅ AsyncAlgorithms.combineLatest() or async let |
536
+ | Pair values from two sources | ✅ AsyncAlgorithms.zip() |
537
+ | Bridge callback API | AsyncStream |
538
+ | Multi-consumer with backpressure | ✅ AsyncChannel |
539
+ | Periodic timer | ✅ AsyncTimerSequence |
540
+ | Simple async iteration | for await in... |
541
+
542
+ > **See**: [async-algorithms.md](async-algorithms.md) for detailed usage examples with real-world patterns.
543
+
544
+ ### Use regular async methods when:
545
+
546
+ - Single value returned
547
+ - No progress updates needed
548
+ - Simple request/response pattern
549
+
550
+ ```swift
551
+ // Use this
552
+ func fetchData() async throws -> Data
553
+
554
+ // Not this
555
+ func fetchData() -> AsyncThrowingStream<Data, Error>
556
+
557
+ > **Course Deep Dive**: This topic is covered in detail in [Lesson 6.3: Deciding between AsyncSequence, AsyncStream, or regular asynchronous methods](https://www.swiftconcurrencycourse.com?utm_source=github&utm_medium=agent-skill&utm_campaign=lesson-reference)
558
+ ```
559
+
560
+ ## Common Patterns
561
+
562
+ ### Progress reporting
563
+
564
+ ```swift
565
+ func download(_ url: URL) -> AsyncThrowingStream<DownloadEvent, Error> {
566
+ AsyncThrowingStream { continuation in
567
+ Task {
568
+ do {
569
+ var progress: Double = 0
570
+ while progress < 1.0 {
571
+ progress += 0.1
572
+ continuation.yield(.progress(progress))
573
+ try await Task.sleep(for: .milliseconds(100))
574
+ }
575
+
576
+ let data = try await URLSession.shared.data(from: url).0
577
+ continuation.yield(.completed(data))
578
+ continuation.finish()
579
+ } catch {
580
+ continuation.finish(throwing: error)
581
+ }
582
+ }
583
+ }
584
+ }
585
+ ```
586
+
587
+ ### Monitoring file system
588
+
589
+ ```swift
590
+ func watchDirectory(_ path: String) -> AsyncStream<FileEvent> {
591
+ AsyncStream(bufferingPolicy: .bufferingNewest(1)) { continuation in
592
+ let source = DispatchSource.makeFileSystemObjectSource(
593
+ fileDescriptor: fd,
594
+ eventMask: .write,
595
+ queue: .main
596
+ )
597
+
598
+ source.setEventHandler {
599
+ continuation.yield(.fileChanged(path))
600
+ }
601
+
602
+ continuation.onTermination = { _ in
603
+ source.cancel()
604
+ }
605
+
606
+ source.resume()
607
+ }
608
+ }
609
+ ```
610
+
611
+ ### Timer/polling
612
+
613
+ ```swift
614
+ func timer(interval: Duration) -> AsyncStream<Date> {
615
+ AsyncStream { continuation in
616
+ Task {
617
+ while !Task.isCancelled {
618
+ continuation.yield(Date())
619
+ try? await Task.sleep(for: interval)
620
+ }
621
+ continuation.finish()
622
+ }
623
+ }
624
+ }
625
+
626
+ // Usage
627
+ for await date in timer(interval: .seconds(1)) {
628
+ print("Tick: \(date)")
629
+ }
630
+ ```
631
+
632
+ ## Best Practices
633
+
634
+ 1. **Always call finish()** - Streams stay alive until terminated
635
+ 2. **Use buffer policies wisely** - Match your use case (latest value vs all values)
636
+ 3. **Handle cancellation** - Set `onTermination` for cleanup
637
+ 4. **Single consumer** - Don't share streams across multiple consumers
638
+ 5. **Prefer streams over closures** - More composable and cancellable
639
+ 6. **Check Task.isCancelled** - Respect cancellation in custom sequences
640
+ 7. **Use throwing variant** - When operations can fail
641
+ 8. **Consider regular async** - If only returning single value
642
+
643
+ ## Debugging
644
+
645
+ ### Add termination logging
646
+
647
+ ```swift
648
+ continuation.onTermination = { reason in
649
+ print("Stream ended: \(reason)")
650
+ }
651
+ ```
652
+
653
+ ### Validate finish() calls
654
+
655
+ ```swift
656
+ // ❌ Forgot to finish
657
+ AsyncStream { continuation in
658
+ continuation.yield(1)
659
+ // Stream never ends!
660
+ }
661
+
662
+ // ✅ Always finish
663
+ AsyncStream { continuation in
664
+ continuation.yield(1)
665
+ continuation.finish()
666
+ }
667
+ ```
668
+
669
+ ### Check for dropped values
670
+
671
+ ```swift
672
+ let stream = AsyncStream(bufferingPolicy: .bufferingNewest(1)) { continuation in
673
+ for i in 1...100 {
674
+ continuation.yield(i)
675
+ print("Yielded: \(i)")
676
+ }
677
+ continuation.finish()
678
+ }
679
+
680
+ // If consumer is slow, many values dropped
681
+ for await value in stream {
682
+ print("Received: \(value)")
683
+ try? await Task.sleep(for: .seconds(1))
684
+ }
685
+ ```
686
+
687
+ ## Common Mistakes Agents Make
688
+
689
+ ```swift
690
+ // ❌ Values after finish() are silently dropped
691
+ continuation.finish()
692
+ continuation.yield(1) // Never received
693
+
694
+ // ❌ Stream never terminates (forgot finish)
695
+ AsyncStream { continuation in
696
+ continuation.yield(1)
697
+ // Missing: continuation.finish()
698
+ }
699
+
700
+ // ❌ Wrapping a single-value API in a stream — use a regular async function instead
701
+ func fetchUser() -> AsyncStream<User> { ... } // Overkill for one result
702
+ ```
703
+
704
+ - **Sharing a single `AsyncStream` between multiple consumers**: Values split unpredictably. There is no built-in broadcast; use `AsyncChannel` for point-to-point multi-consumer patterns.
705
+ - **Forgetting `onTermination`** when bridging delegate or observer APIs, causing resources to leak.
706
+
707
+ ## Further Learning
708
+
709
+ For real-world migration examples, performance patterns, and advanced stream techniques, see [Swift Concurrency Course](https://www.swiftconcurrencycourse.com).
710
+