claudecode-omc 5.6.7 → 5.6.8

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 (123) hide show
  1. package/.local/skills/THIRD_PARTY_LICENSES/AvdLee-SwiftUI-Agent-Skill.LICENSE +21 -0
  2. package/.local/skills/THIRD_PARTY_LICENSES/Dimillian-Skills.LICENSE +21 -0
  3. package/.local/skills/THIRD_PARTY_LICENSES/README.md +36 -0
  4. package/.local/skills/THIRD_PARTY_LICENSES/twostraws-swiftui-agent-skill.LICENSE +21 -0
  5. package/.local/skills/ios-debugger-agent/SKILL.md +51 -0
  6. package/.local/skills/ios-debugger-agent/agents/openai.yaml +4 -0
  7. package/.local/skills/swift-concurrency-expert/SKILL.md +105 -0
  8. package/.local/skills/swift-concurrency-expert/agents/openai.yaml +4 -0
  9. package/.local/skills/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
  10. package/.local/skills/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
  11. package/.local/skills/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
  12. package/.local/skills/swiftui-expert-skill/SKILL.md +162 -0
  13. package/.local/skills/swiftui-expert-skill/references/accessibility-patterns.md +215 -0
  14. package/.local/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  15. package/.local/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  16. package/.local/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  17. package/.local/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  18. package/.local/skills/swiftui-expert-skill/references/charts.md +602 -0
  19. package/.local/skills/swiftui-expert-skill/references/focus-patterns.md +299 -0
  20. package/.local/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  21. package/.local/skills/swiftui-expert-skill/references/latest-apis.md +488 -0
  22. package/.local/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  23. package/.local/skills/swiftui-expert-skill/references/liquid-glass.md +423 -0
  24. package/.local/skills/swiftui-expert-skill/references/list-patterns.md +446 -0
  25. package/.local/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  26. package/.local/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  27. package/.local/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  28. package/.local/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  29. package/.local/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  30. package/.local/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  31. package/.local/skills/swiftui-expert-skill/references/state-management.md +388 -0
  32. package/.local/skills/swiftui-expert-skill/references/text-patterns.md +32 -0
  33. package/.local/skills/swiftui-expert-skill/references/trace-analysis.md +295 -0
  34. package/.local/skills/swiftui-expert-skill/references/trace-recording.md +134 -0
  35. package/.local/skills/swiftui-expert-skill/references/view-structure.md +780 -0
  36. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/analyze_trace.cpython-313.pyc +0 -0
  37. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/record_trace.cpython-313.pyc +0 -0
  38. package/.local/skills/swiftui-expert-skill/scripts/analyze_trace.py +301 -0
  39. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__init__.py +1 -0
  40. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/__init__.cpython-313.pyc +0 -0
  41. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/causes.cpython-313.pyc +0 -0
  42. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/correlate.cpython-313.pyc +0 -0
  43. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/events.cpython-313.pyc +0 -0
  44. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hangs.cpython-313.pyc +0 -0
  45. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hitches.cpython-313.pyc +0 -0
  46. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/summary.cpython-313.pyc +0 -0
  47. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/swiftui.cpython-313.pyc +0 -0
  48. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/time_profiler.cpython-313.pyc +0 -0
  49. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xctrace.cpython-313.pyc +0 -0
  50. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xml_utils.cpython-313.pyc +0 -0
  51. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/causes.py +187 -0
  52. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/correlate.py +179 -0
  53. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/events.py +291 -0
  54. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hangs.py +108 -0
  55. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hitches.py +145 -0
  56. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/summary.py +243 -0
  57. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/swiftui.py +195 -0
  58. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/time_profiler.py +135 -0
  59. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xctrace.py +117 -0
  60. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xml_utils.py +224 -0
  61. package/.local/skills/swiftui-expert-skill/scripts/record_trace.py +252 -0
  62. package/.local/skills/swiftui-liquid-glass/SKILL.md +90 -0
  63. package/.local/skills/swiftui-liquid-glass/agents/openai.yaml +4 -0
  64. package/.local/skills/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  65. package/.local/skills/swiftui-performance-audit/SKILL.md +106 -0
  66. package/.local/skills/swiftui-performance-audit/agents/openai.yaml +4 -0
  67. package/.local/skills/swiftui-performance-audit/references/code-smells.md +150 -0
  68. package/.local/skills/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  69. package/.local/skills/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  70. package/.local/skills/swiftui-performance-audit/references/profiling-intake.md +44 -0
  71. package/.local/skills/swiftui-performance-audit/references/report-template.md +47 -0
  72. package/.local/skills/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  73. package/.local/skills/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  74. package/.local/skills/swiftui-pro/SKILL.md +108 -0
  75. package/.local/skills/swiftui-pro/agents/openai.yaml +10 -0
  76. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  77. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  78. package/.local/skills/swiftui-pro/references/accessibility.md +13 -0
  79. package/.local/skills/swiftui-pro/references/api.md +39 -0
  80. package/.local/skills/swiftui-pro/references/data.md +43 -0
  81. package/.local/skills/swiftui-pro/references/design.md +32 -0
  82. package/.local/skills/swiftui-pro/references/hygiene.md +9 -0
  83. package/.local/skills/swiftui-pro/references/navigation.md +14 -0
  84. package/.local/skills/swiftui-pro/references/performance.md +46 -0
  85. package/.local/skills/swiftui-pro/references/swift.md +56 -0
  86. package/.local/skills/swiftui-pro/references/views.md +36 -0
  87. package/.local/skills/swiftui-ui-patterns/SKILL.md +95 -0
  88. package/.local/skills/swiftui-ui-patterns/agents/openai.yaml +4 -0
  89. package/.local/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  90. package/.local/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  91. package/.local/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  92. package/.local/skills/swiftui-ui-patterns/references/controls.md +57 -0
  93. package/.local/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  94. package/.local/skills/swiftui-ui-patterns/references/focus.md +90 -0
  95. package/.local/skills/swiftui-ui-patterns/references/form.md +97 -0
  96. package/.local/skills/swiftui-ui-patterns/references/grids.md +71 -0
  97. package/.local/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  98. package/.local/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  99. package/.local/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  100. package/.local/skills/swiftui-ui-patterns/references/list.md +86 -0
  101. package/.local/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  102. package/.local/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  103. package/.local/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  104. package/.local/skills/swiftui-ui-patterns/references/media.md +73 -0
  105. package/.local/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  106. package/.local/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  107. package/.local/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  108. package/.local/skills/swiftui-ui-patterns/references/performance.md +62 -0
  109. package/.local/skills/swiftui-ui-patterns/references/previews.md +48 -0
  110. package/.local/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  111. package/.local/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  112. package/.local/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  113. package/.local/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  114. package/.local/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  115. package/.local/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  116. package/.local/skills/swiftui-ui-patterns/references/theming.md +71 -0
  117. package/.local/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  118. package/.local/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
  119. package/.local/skills/swiftui-view-refactor/SKILL.md +202 -0
  120. package/.local/skills/swiftui-view-refactor/agents/openai.yaml +4 -0
  121. package/.local/skills/swiftui-view-refactor/references/mv-patterns.md +161 -0
  122. package/bundled/manifest.json +1 -1
  123. package/package.json +1 -1
@@ -0,0 +1,299 @@
1
+ # SwiftUI Focus Patterns Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [@FocusState](#focusstate)
6
+ - [Making Views Focusable](#making-views-focusable)
7
+ - [Focused Values for Commands and Menus](#focused-values-for-commands-and-menus)
8
+ - [Default Focus](#default-focus)
9
+ - [Focus Scope and Sections](#focus-scope-and-sections)
10
+ - [Focus Effects](#focus-effects)
11
+ - [Search Focus](#search-focus)
12
+ - [Common Pitfalls](#common-pitfalls)
13
+
14
+ ## @FocusState
15
+
16
+ Always mark `@FocusState` as `private`. Use `Bool` for a single field, an optional `Hashable` enum for multiple fields.
17
+
18
+ ### Single field
19
+
20
+ ```swift
21
+ @FocusState private var isFocused: Bool
22
+
23
+ TextField("Email", text: $email)
24
+ .focused($isFocused)
25
+ ```
26
+
27
+ ### Multiple fields
28
+
29
+ ```swift
30
+ enum Field: Hashable { case name, email, password }
31
+ @FocusState private var focusedField: Field?
32
+
33
+ TextField("Name", text: $name)
34
+ .focused($focusedField, equals: .name)
35
+ TextField("Email", text: $email)
36
+ .focused($focusedField, equals: .email)
37
+ ```
38
+
39
+ Set `focusedField = .email` to move focus programmatically; set `nil` to dismiss the keyboard.
40
+
41
+ ### `focused(_:)` vs `focused(_:equals:)` with nested views
42
+
43
+ `.focused($bool)` reports `true` when the modified view *or any focusable descendant* has focus. `.focused($enum, equals:)` reports its value only when that specific view receives focus.
44
+
45
+ ```swift
46
+ enum Focus: Hashable { case container, field }
47
+ @FocusState private var focus: Focus?
48
+
49
+ VStack {
50
+ TextField("Name", text: $name)
51
+ .focused($focus, equals: .field)
52
+ }
53
+ .focusable()
54
+ .focused($focus, equals: .container)
55
+ ```
56
+
57
+ With `focused(_:equals:)` and a single `@FocusState`, SwiftUI distinguishes the container *receiving* focus from the container merely *containing* focus.
58
+
59
+ ### `isFocused` environment value
60
+
61
+ Read-only environment value that returns `true` when the nearest focusable ancestor has focus. Useful for styling non-focusable child views.
62
+
63
+ ```swift
64
+ struct HighlightWrapper: View {
65
+ @Environment(\.isFocused) private var isFocused
66
+
67
+ var body: some View {
68
+ content
69
+ .background(isFocused ? Color.accentColor.opacity(0.1) : .clear)
70
+ }
71
+ }
72
+ ```
73
+
74
+ ## Making Views Focusable
75
+
76
+ ### `.focusable(_:)`
77
+
78
+ Makes a non-text-input view participate in the focus system. Focused views can respond to keyboard events via `onKeyPress` and menu commands like Edit > Delete via `onDeleteCommand`.
79
+
80
+ ```swift
81
+ struct SelectableCard: View {
82
+ @FocusState private var isFocused: Bool
83
+
84
+ var body: some View {
85
+ CardContent()
86
+ .focusable()
87
+ .focused($isFocused)
88
+ .border(isFocused ? Color.accentColor : .clear)
89
+ .onDeleteCommand { deleteCard() }
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### `.focusable(_:interactions:)` (iOS 17+)
95
+
96
+ Controls which focus-driven interactions the view supports via `FocusInteractions`:
97
+
98
+ - `.activate` -- Button-like: only focusable when system-wide keyboard navigation is on (macOS/iOS)
99
+ - `.edit` -- Captures keyboard/Digital Crown input
100
+ - `.automatic` -- Platform default (both activate and edit)
101
+
102
+ ```swift
103
+ MyTapGestureView(...)
104
+ .focusable(interactions: .activate)
105
+ ```
106
+
107
+ Use `.activate` for custom button-like views that should match system keyboard-navigation behavior.
108
+
109
+ ## Focused Values for Commands and Menus
110
+
111
+ Focused values let parent views (App, Scene, Commands) read state from whichever view currently has focus. Use for enabling/disabling menu commands based on the focused document or selection.
112
+
113
+ ### Declare with `@Entry`
114
+
115
+ ```swift
116
+ extension FocusedValues {
117
+ @Entry var selectedDocument: Binding<Document>?
118
+ }
119
+ ```
120
+
121
+ Focused values are typically optional (default is `nil` when no view publishes them), but you can also use non-optional entries when you have a sensible default value.
122
+
123
+ ### Publish from views
124
+
125
+ ```swift
126
+ // View-scoped: available when this view (or descendant) has focus
127
+ .focusedValue(\.selectedDocument, $document)
128
+
129
+ // Scene-scoped: available when this scene has focus
130
+ .focusedSceneValue(\.selectedDocument, $document)
131
+ ```
132
+
133
+ ### Consume in commands
134
+
135
+ `@FocusedValue` reads the value; `@FocusedBinding` unwraps a `Binding` automatically.
136
+
137
+ ```swift
138
+ @main
139
+ struct MyApp: App {
140
+ @FocusedBinding(\.selectedDocument) var document
141
+
142
+ var body: some Scene {
143
+ WindowGroup {
144
+ ContentView()
145
+ }
146
+ .commands {
147
+ CommandGroup(after: .pasteboard) {
148
+ Button("Duplicate") { document?.duplicate() }
149
+ .disabled(document == nil)
150
+ }
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ ### `@FocusedObject` (iOS 16+)
157
+
158
+ For `ObservableObject` types. The view invalidates when the focused object changes.
159
+
160
+ ```swift
161
+ // Publish
162
+ .focusedObject(myObservableModel)
163
+
164
+ // Consume
165
+ @FocusedObject var model: MyModel?
166
+ ```
167
+
168
+ Scene-scoped variant: `.focusedSceneObject(_:)`.
169
+
170
+ ## Default Focus
171
+
172
+ ### `.defaultFocus(_:_:priority:)` (iOS 17+, macOS 13+, tvOS 16+)
173
+
174
+ Prefer `.defaultFocus` over setting `@FocusState` in `onAppear` for initial focus placement.
175
+
176
+ ```swift
177
+ @FocusState private var focusedField: Field?
178
+
179
+ VStack {
180
+ TextField("Name", text: $name)
181
+ .focused($focusedField, equals: .name)
182
+ TextField("Email", text: $email)
183
+ .focused($focusedField, equals: .email)
184
+ }
185
+ .defaultFocus($focusedField, .email)
186
+ ```
187
+
188
+ **Priority**: `.automatic` (default) applies on window appearance and programmatic focus changes. `.userInitiated` also applies during user-driven focus navigation.
189
+
190
+ ### `prefersDefaultFocus(_:in:)` (macOS/tvOS/watchOS)
191
+
192
+ Used with `.focusScope(_:)` to mark a preferred default target within a scoped region.
193
+
194
+ ### `resetFocus` environment action (macOS/tvOS/watchOS)
195
+
196
+ Re-evaluates default focus within a namespace.
197
+
198
+ ```swift
199
+ @Namespace var scopeID
200
+ @Environment(\.resetFocus) private var resetFocus
201
+
202
+ Button("Reset") { resetFocus(in: scopeID) }
203
+ ```
204
+
205
+ ## Focus Scope and Sections
206
+
207
+ ### `.focusScope(_:)` (macOS/tvOS/watchOS)
208
+
209
+ Limits default focus preferences to a namespace. Use with `prefersDefaultFocus` and `resetFocus`.
210
+
211
+ ### `.focusSection()` (macOS 13+, tvOS 15+)
212
+
213
+ Guides directional and sequential focus movement through a group of focusable descendants. Useful when focusable views are spatially separated and directional navigation would otherwise skip them.
214
+
215
+ ```swift
216
+ HStack {
217
+ VStack { Button("1") {}; Button("2") {}; Spacer() }
218
+ Spacer()
219
+ VStack { Spacer(); Button("A") {}; Button("B") {} }
220
+ .focusSection()
221
+ }
222
+ ```
223
+
224
+ Without `.focusSection()`, swiping right from buttons 1/2 finds nothing. With it, the VStack receives directional focus and delivers it to its first focusable child.
225
+
226
+ ## Focus Effects
227
+
228
+ ### `.focusEffectDisabled(_:)`
229
+
230
+ Suppresses the system focus ring (macOS) or hover effect. Use when providing custom focus visuals.
231
+
232
+ ```swift
233
+ MyCustomCard()
234
+ .focusable()
235
+ .focusEffectDisabled()
236
+ .overlay { customFocusRing }
237
+ ```
238
+
239
+ `isFocusEffectEnabled` environment value reads the current state.
240
+
241
+ ## Search Focus
242
+
243
+ ### `.searchFocused(_:)` / `.searchFocused(_:equals:)`
244
+
245
+ Bind focus state to the search field associated with the nearest `.searchable` modifier. Works like `.focused` but targets the search bar.
246
+
247
+ ```swift
248
+ @FocusState private var isSearchFocused: Bool
249
+
250
+ NavigationStack {
251
+ ContentView()
252
+ .searchable(text: $query)
253
+ .searchFocused($isSearchFocused)
254
+ }
255
+
256
+ // Programmatically focus the search bar
257
+ Button("Search") { isSearchFocused = true }
258
+ ```
259
+
260
+ ## Common Pitfalls
261
+
262
+ ### Redundant `@FocusState` writes revoke focus
263
+
264
+ `.focusable()` + `.focused()` handles focus-on-click natively. Adding a tap gesture that *also* writes to `@FocusState` triggers a redundant state write, causing a second body evaluation that revokes focus. The result: focus briefly appears then disappears, and key commands like `onDeleteCommand` stop working.
265
+
266
+ ```swift
267
+ // WRONG -- tap gesture redundantly sets focus, causing double evaluation
268
+ CardView()
269
+ .focusable()
270
+ .focused($isFocused)
271
+ .onTapGesture { isFocused = true } // Remove this line
272
+
273
+ // CORRECT -- let .focusable() + .focused() handle it
274
+ CardView()
275
+ .focusable()
276
+ .focused($isFocused)
277
+ ```
278
+
279
+ ### Ambiguous focus bindings
280
+
281
+ Binding the same enum case to multiple views is ambiguous. SwiftUI picks the first candidate and emits a runtime warning.
282
+
283
+ ```swift
284
+ // WRONG -- .name bound to two views
285
+ TextField("Name", text: $name)
286
+ .focused($focusedField, equals: .name)
287
+ TextField("Full Name", text: $fullName)
288
+ .focused($focusedField, equals: .name) // ambiguous
289
+ ```
290
+
291
+ Always use distinct enum cases for each focusable view.
292
+
293
+ ### `.onAppear` focus timing
294
+
295
+ Setting `@FocusState` in `.onAppear` may fail if the view tree hasn't settled. Prefer `.defaultFocus` (iOS 17+) for reliable initial focus. If you must use `.onAppear`, wrap in `DispatchQueue.main.async` as a last resort.
296
+
297
+ ### Missing `.focusable()` for non-text views
298
+
299
+ `TextField` and `SecureField` are implicitly focusable. Custom views (stacks, shapes, images) are not. Forgetting `.focusable()` means `.focused()` bindings have no effect and key event handlers never fire.
@@ -0,0 +1,203 @@
1
+ # SwiftUI Image Optimization Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [AsyncImage Best Practices](#asyncimage-best-practices)
6
+ - [Image Decoding and Downsampling (Optional Optimization)](#image-decoding-and-downsampling-optional-optimization)
7
+ - [UIImage Loading and Memory](#uiimage-loading-and-memory)
8
+ - [SF Symbols](#sf-symbols)
9
+ - [Summary Checklist](#summary-checklist)
10
+
11
+ ## AsyncImage Best Practices
12
+
13
+ ### Basic AsyncImage with Phase Handling
14
+
15
+ ```swift
16
+ // Good - handles loading and error states
17
+ AsyncImage(url: imageURL) { phase in
18
+ switch phase {
19
+ case .empty:
20
+ ProgressView()
21
+ case .success(let image):
22
+ image
23
+ .resizable()
24
+ .aspectRatio(contentMode: .fit)
25
+ case .failure:
26
+ Image(systemName: "photo")
27
+ .foregroundStyle(.secondary)
28
+ @unknown default:
29
+ EmptyView()
30
+ }
31
+ }
32
+ .frame(width: 200, height: 200)
33
+ ```
34
+
35
+ For custom placeholders, replace `ProgressView()` in the `.empty` case with your placeholder view. Add `.transition(.opacity)` to the success case and `.animation(.easeInOut, value: imageURL)` to the container for fade-in transitions.
36
+
37
+ ## Image Decoding and Downsampling (Optional Optimization)
38
+
39
+ **When you encounter `UIImage(data:)` usage, consider suggesting image downsampling as a potential performance improvement**, especially for large images in lists or grids.
40
+
41
+ ### Current Pattern That Could Be Optimized
42
+
43
+ ```swift
44
+ // Current pattern - decodes full image on main thread
45
+ // Unsafe - force unwrap can crash if imageData is invalid
46
+ Image(uiImage: UIImage(data: imageData)!)
47
+ .resizable()
48
+ .aspectRatio(contentMode: .fit)
49
+ .frame(width: 200, height: 200)
50
+ ```
51
+
52
+ ### Suggested Optimization Pattern
53
+
54
+ ```swift
55
+ // Suggested optimization - decode and downsample off main thread
56
+ struct OptimizedImageView: View {
57
+ let imageData: Data
58
+ let targetSize: CGSize
59
+ @State private var processedImage: UIImage?
60
+
61
+ var body: some View {
62
+ Group {
63
+ if let processedImage {
64
+ Image(uiImage: processedImage)
65
+ .resizable()
66
+ .aspectRatio(contentMode: .fit)
67
+ } else {
68
+ ProgressView()
69
+ }
70
+ }
71
+ .task {
72
+ processedImage = await decodeAndDownsample(imageData, targetSize: targetSize)
73
+ }
74
+ }
75
+
76
+ private func decodeAndDownsample(_ data: Data, targetSize: CGSize) async -> UIImage? {
77
+ await Task.detached {
78
+ guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
79
+ return nil
80
+ }
81
+
82
+ let options: [CFString: Any] = [
83
+ kCGImageSourceThumbnailMaxPixelSize: max(targetSize.width, targetSize.height),
84
+ kCGImageSourceCreateThumbnailFromImageAlways: true,
85
+ kCGImageSourceCreateThumbnailWithTransform: true
86
+ ]
87
+
88
+ guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, options as CFDictionary) else {
89
+ return nil
90
+ }
91
+
92
+ return UIImage(cgImage: cgImage)
93
+ }.value
94
+ }
95
+ }
96
+
97
+ // Usage
98
+ OptimizedImageView(
99
+ imageData: imageData,
100
+ targetSize: CGSize(width: 200, height: 200)
101
+ )
102
+ ```
103
+
104
+ ### Reusable Downsampling Actor
105
+
106
+ For production use, wrap the logic in an `actor` with scale-aware sizing and cache-disabled source options:
107
+
108
+ ```swift
109
+ actor ImageProcessor {
110
+ func downsample(data: Data, targetSize: CGSize) -> UIImage? {
111
+ let scale = await UIScreen.main.scale
112
+ let maxPixel = max(targetSize.width, targetSize.height) * scale
113
+ let sourceOptions: [CFString: Any] = [kCGImageSourceShouldCache: false]
114
+ guard let source = CGImageSourceCreateWithData(data as CFData, sourceOptions as CFDictionary) else { return nil }
115
+ let downsampleOptions: [CFString: Any] = [
116
+ kCGImageSourceCreateThumbnailFromImageAlways: true,
117
+ kCGImageSourceThumbnailMaxPixelSize: maxPixel,
118
+ kCGImageSourceCreateThumbnailWithTransform: true,
119
+ kCGImageSourceShouldCacheImmediately: true
120
+ ]
121
+ guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions as CFDictionary) else { return nil }
122
+ return UIImage(cgImage: cgImage)
123
+ }
124
+ }
125
+ ```
126
+
127
+ Key details: `kCGImageSourceShouldCache: false` on the source prevents the full-resolution image from being cached in memory. Multiplying `targetSize` by `UIScreen.main.scale` ensures the thumbnail is sharp on Retina displays. `kCGImageSourceShouldCacheImmediately: true` on the thumbnail forces decoding at creation time rather than at first render.
128
+
129
+ ### When to Suggest This Optimization
130
+
131
+ Mention this optimization when you see `UIImage(data:)` usage, particularly in:
132
+ - Scrollable content (List, ScrollView with LazyVStack/LazyHStack)
133
+ - Grid layouts with many images
134
+ - Image galleries or carousels
135
+ - Any scenario where large images are displayed at smaller sizes
136
+
137
+ **Don't automatically apply it**—present it as an optional improvement for performance-sensitive scenarios.
138
+
139
+ ## UIImage Loading and Memory
140
+
141
+ ### UIImage(named:) Caches in System Cache
142
+
143
+ `UIImage(named:)` adds images to the system cache, which can cause memory spikes when loading many images (e.g., in a slider or gallery). For single-use or frequently-rotated images, use `UIImage(contentsOfFile:)` to bypass the cache:
144
+
145
+ ```swift
146
+ // Caches in system cache -- memory builds up
147
+ let image = UIImage(named: "Wallpapers/image_001.jpg")
148
+
149
+ // No system caching -- memory stays flat
150
+ guard let path = Bundle.main.path(forResource: "Wallpapers/image_001.jpg", ofType: nil) else { return nil }
151
+ let image = UIImage(contentsOfFile: path)
152
+ ```
153
+
154
+ ### NSCache for Controlled Image Caching
155
+
156
+ When image processing (resizing, filtering) is needed, use `NSCache` with a `countLimit` to bound memory instead of relying on system caching:
157
+
158
+ ```swift
159
+ struct ImageCache {
160
+ private let cache = NSCache<NSString, UIImage>()
161
+
162
+ init(countLimit: Int = 50) {
163
+ cache.countLimit = countLimit
164
+ }
165
+
166
+ subscript(key: String) -> UIImage? {
167
+ get { cache.object(forKey: key as NSString) }
168
+ nonmutating set {
169
+ if let newValue {
170
+ cache.setObject(newValue, forKey: key as NSString)
171
+ } else {
172
+ cache.removeObject(forKey: key as NSString)
173
+ }
174
+ }
175
+ }
176
+ }
177
+ ```
178
+
179
+ ## SF Symbols
180
+
181
+ ```swift
182
+ Image(systemName: "star.fill")
183
+ .foregroundStyle(.yellow)
184
+ .symbolRenderingMode(.multicolor) // or .hierarchical, .palette, .monochrome
185
+
186
+ // Animated symbols (iOS 17+)
187
+ Image(systemName: "antenna.radiowaves.left.and.right")
188
+ .symbolEffect(.variableColor)
189
+ ```
190
+
191
+ Variants are available via naming convention: `star.circle.fill`, `star.square.fill`, `folder.badge.plus`.
192
+
193
+ ## Summary Checklist
194
+
195
+ - [ ] Use `AsyncImage` with proper phase handling
196
+ - [ ] Handle empty, success, and failure states
197
+ - [ ] Consider downsampling for `UIImage(data:)` in performance-sensitive scenarios
198
+ - [ ] Decode and downsample images off the main thread
199
+ - [ ] Use appropriate target sizes for downsampling
200
+ - [ ] Consider image caching for frequently accessed images
201
+ - [ ] Use SF Symbols with appropriate rendering modes
202
+
203
+ **Performance Note**: Image downsampling is an optional optimization. Only suggest it when you encounter `UIImage(data:)` usage in performance-sensitive contexts like scrollable lists or grids.