claudecode-omc 5.6.6 → 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 (179) 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/h5-to-swiftui/SKILL.md +201 -0
  6. package/.local/skills/h5-to-swiftui/assets/calibration/README.md +176 -0
  7. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/index.html +52 -0
  8. package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/style.css +133 -0
  9. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Package.swift +26 -0
  10. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Sources/CalibrationScreen/CalibrationScreen.swift +142 -0
  11. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Package.swift +32 -0
  12. package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Sources/CalibrationScreenDivergent/CalibrationScreenDivergent.swift +122 -0
  13. package/.local/skills/h5-to-swiftui/assets/calibration/tokens.json +42 -0
  14. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/index.html +14 -0
  15. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/package.json +20 -0
  16. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/001.json +96 -0
  17. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/index.json +89 -0
  18. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.jsx +22 -0
  19. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.module.css +11 -0
  20. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.jsx +53 -0
  21. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.module.css +139 -0
  22. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.jsx +37 -0
  23. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.module.css +72 -0
  24. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.jsx +30 -0
  25. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.module.css +50 -0
  26. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.jsx +159 -0
  27. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.module.css +21 -0
  28. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/main.jsx +12 -0
  29. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.jsx +182 -0
  30. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.module.css +294 -0
  31. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.jsx +147 -0
  32. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.module.css +161 -0
  33. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/global.css +50 -0
  34. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/tokens.css +103 -0
  35. package/.local/skills/h5-to-swiftui/assets/sample-h5-react/vite.config.js +6 -0
  36. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/data/tasks.js +67 -0
  37. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/index.html +26 -0
  38. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/router.js +73 -0
  39. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/detail.js +164 -0
  40. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/home.js +53 -0
  41. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/list.js +87 -0
  42. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/app.css +342 -0
  43. package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/tokens.css +68 -0
  44. package/.local/skills/h5-to-swiftui/references/css-to-swiftui-map.md +205 -0
  45. package/.local/skills/h5-to-swiftui/references/design-token-extraction.md +209 -0
  46. package/.local/skills/h5-to-swiftui/references/high-risk-triage.md +209 -0
  47. package/.local/skills/h5-to-swiftui/references/render-equivalence-calibration.md +193 -0
  48. package/.local/skills/h5-to-swiftui/references/stack-detection.md +160 -0
  49. package/.local/skills/h5-to-swiftui/references/visual-diff-loop-protocol.md +365 -0
  50. package/.local/skills/h5-to-swiftui/scripts/_calib-consts.mjs +150 -0
  51. package/.local/skills/h5-to-swiftui/scripts/_imglib.mjs +547 -0
  52. package/.local/skills/h5-to-swiftui/scripts/_provenance.mjs +123 -0
  53. package/.local/skills/h5-to-swiftui/scripts/calibrate-render.mjs +625 -0
  54. package/.local/skills/h5-to-swiftui/scripts/capture-reference.mjs +386 -0
  55. package/.local/skills/h5-to-swiftui/scripts/detect-stack.mjs +305 -0
  56. package/.local/skills/h5-to-swiftui/scripts/evaluate-convergence.mjs +1093 -0
  57. package/.local/skills/h5-to-swiftui/scripts/extract-tokens.mjs +600 -0
  58. package/.local/skills/h5-to-swiftui/scripts/mark-overlay.mjs +379 -0
  59. package/.local/skills/h5-to-swiftui/scripts/pixel-diff.mjs +530 -0
  60. package/.local/skills/h5-to-swiftui/scripts/sim-screenshot.sh +544 -0
  61. package/.local/skills/ios-debugger-agent/SKILL.md +51 -0
  62. package/.local/skills/ios-debugger-agent/agents/openai.yaml +4 -0
  63. package/.local/skills/swift-concurrency-expert/SKILL.md +105 -0
  64. package/.local/skills/swift-concurrency-expert/agents/openai.yaml +4 -0
  65. package/.local/skills/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
  66. package/.local/skills/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
  67. package/.local/skills/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
  68. package/.local/skills/swiftui-expert-skill/SKILL.md +162 -0
  69. package/.local/skills/swiftui-expert-skill/references/accessibility-patterns.md +215 -0
  70. package/.local/skills/swiftui-expert-skill/references/animation-advanced.md +403 -0
  71. package/.local/skills/swiftui-expert-skill/references/animation-basics.md +284 -0
  72. package/.local/skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
  73. package/.local/skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
  74. package/.local/skills/swiftui-expert-skill/references/charts.md +602 -0
  75. package/.local/skills/swiftui-expert-skill/references/focus-patterns.md +299 -0
  76. package/.local/skills/swiftui-expert-skill/references/image-optimization.md +203 -0
  77. package/.local/skills/swiftui-expert-skill/references/latest-apis.md +488 -0
  78. package/.local/skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
  79. package/.local/skills/swiftui-expert-skill/references/liquid-glass.md +423 -0
  80. package/.local/skills/swiftui-expert-skill/references/list-patterns.md +446 -0
  81. package/.local/skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
  82. package/.local/skills/swiftui-expert-skill/references/macos-views.md +357 -0
  83. package/.local/skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
  84. package/.local/skills/swiftui-expert-skill/references/performance-patterns.md +403 -0
  85. package/.local/skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
  86. package/.local/skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
  87. package/.local/skills/swiftui-expert-skill/references/state-management.md +388 -0
  88. package/.local/skills/swiftui-expert-skill/references/text-patterns.md +32 -0
  89. package/.local/skills/swiftui-expert-skill/references/trace-analysis.md +295 -0
  90. package/.local/skills/swiftui-expert-skill/references/trace-recording.md +134 -0
  91. package/.local/skills/swiftui-expert-skill/references/view-structure.md +780 -0
  92. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/analyze_trace.cpython-313.pyc +0 -0
  93. package/.local/skills/swiftui-expert-skill/scripts/__pycache__/record_trace.cpython-313.pyc +0 -0
  94. package/.local/skills/swiftui-expert-skill/scripts/analyze_trace.py +301 -0
  95. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__init__.py +1 -0
  96. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/__init__.cpython-313.pyc +0 -0
  97. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/causes.cpython-313.pyc +0 -0
  98. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/correlate.cpython-313.pyc +0 -0
  99. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/events.cpython-313.pyc +0 -0
  100. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hangs.cpython-313.pyc +0 -0
  101. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/hitches.cpython-313.pyc +0 -0
  102. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/summary.cpython-313.pyc +0 -0
  103. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/swiftui.cpython-313.pyc +0 -0
  104. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/time_profiler.cpython-313.pyc +0 -0
  105. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xctrace.cpython-313.pyc +0 -0
  106. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/__pycache__/xml_utils.cpython-313.pyc +0 -0
  107. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/causes.py +187 -0
  108. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/correlate.py +179 -0
  109. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/events.py +291 -0
  110. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hangs.py +108 -0
  111. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/hitches.py +145 -0
  112. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/summary.py +243 -0
  113. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/swiftui.py +195 -0
  114. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/time_profiler.py +135 -0
  115. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xctrace.py +117 -0
  116. package/.local/skills/swiftui-expert-skill/scripts/instruments_parser/xml_utils.py +224 -0
  117. package/.local/skills/swiftui-expert-skill/scripts/record_trace.py +252 -0
  118. package/.local/skills/swiftui-liquid-glass/SKILL.md +90 -0
  119. package/.local/skills/swiftui-liquid-glass/agents/openai.yaml +4 -0
  120. package/.local/skills/swiftui-liquid-glass/references/liquid-glass.md +280 -0
  121. package/.local/skills/swiftui-performance-audit/SKILL.md +106 -0
  122. package/.local/skills/swiftui-performance-audit/agents/openai.yaml +4 -0
  123. package/.local/skills/swiftui-performance-audit/references/code-smells.md +150 -0
  124. package/.local/skills/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
  125. package/.local/skills/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
  126. package/.local/skills/swiftui-performance-audit/references/profiling-intake.md +44 -0
  127. package/.local/skills/swiftui-performance-audit/references/report-template.md +47 -0
  128. package/.local/skills/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
  129. package/.local/skills/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
  130. package/.local/skills/swiftui-pro/SKILL.md +108 -0
  131. package/.local/skills/swiftui-pro/agents/openai.yaml +10 -0
  132. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.png +0 -0
  133. package/.local/skills/swiftui-pro/assets/swiftui-pro-icon.svg +29 -0
  134. package/.local/skills/swiftui-pro/references/accessibility.md +13 -0
  135. package/.local/skills/swiftui-pro/references/api.md +39 -0
  136. package/.local/skills/swiftui-pro/references/data.md +43 -0
  137. package/.local/skills/swiftui-pro/references/design.md +32 -0
  138. package/.local/skills/swiftui-pro/references/hygiene.md +9 -0
  139. package/.local/skills/swiftui-pro/references/navigation.md +14 -0
  140. package/.local/skills/swiftui-pro/references/performance.md +46 -0
  141. package/.local/skills/swiftui-pro/references/swift.md +56 -0
  142. package/.local/skills/swiftui-pro/references/views.md +36 -0
  143. package/.local/skills/swiftui-ui-patterns/SKILL.md +95 -0
  144. package/.local/skills/swiftui-ui-patterns/agents/openai.yaml +4 -0
  145. package/.local/skills/swiftui-ui-patterns/references/app-wiring.md +201 -0
  146. package/.local/skills/swiftui-ui-patterns/references/async-state.md +96 -0
  147. package/.local/skills/swiftui-ui-patterns/references/components-index.md +50 -0
  148. package/.local/skills/swiftui-ui-patterns/references/controls.md +57 -0
  149. package/.local/skills/swiftui-ui-patterns/references/deeplinks.md +66 -0
  150. package/.local/skills/swiftui-ui-patterns/references/focus.md +90 -0
  151. package/.local/skills/swiftui-ui-patterns/references/form.md +97 -0
  152. package/.local/skills/swiftui-ui-patterns/references/grids.md +71 -0
  153. package/.local/skills/swiftui-ui-patterns/references/haptics.md +71 -0
  154. package/.local/skills/swiftui-ui-patterns/references/input-toolbar.md +51 -0
  155. package/.local/skills/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
  156. package/.local/skills/swiftui-ui-patterns/references/list.md +86 -0
  157. package/.local/skills/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
  158. package/.local/skills/swiftui-ui-patterns/references/macos-settings.md +71 -0
  159. package/.local/skills/swiftui-ui-patterns/references/matched-transitions.md +59 -0
  160. package/.local/skills/swiftui-ui-patterns/references/media.md +73 -0
  161. package/.local/skills/swiftui-ui-patterns/references/menu-bar.md +101 -0
  162. package/.local/skills/swiftui-ui-patterns/references/navigationstack.md +159 -0
  163. package/.local/skills/swiftui-ui-patterns/references/overlay.md +45 -0
  164. package/.local/skills/swiftui-ui-patterns/references/performance.md +62 -0
  165. package/.local/skills/swiftui-ui-patterns/references/previews.md +48 -0
  166. package/.local/skills/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
  167. package/.local/skills/swiftui-ui-patterns/references/scrollview.md +87 -0
  168. package/.local/skills/swiftui-ui-patterns/references/searchable.md +71 -0
  169. package/.local/skills/swiftui-ui-patterns/references/sheets.md +155 -0
  170. package/.local/skills/swiftui-ui-patterns/references/split-views.md +72 -0
  171. package/.local/skills/swiftui-ui-patterns/references/tabview.md +114 -0
  172. package/.local/skills/swiftui-ui-patterns/references/theming.md +71 -0
  173. package/.local/skills/swiftui-ui-patterns/references/title-menus.md +93 -0
  174. package/.local/skills/swiftui-ui-patterns/references/top-bar.md +49 -0
  175. package/.local/skills/swiftui-view-refactor/SKILL.md +202 -0
  176. package/.local/skills/swiftui-view-refactor/agents/openai.yaml +4 -0
  177. package/.local/skills/swiftui-view-refactor/references/mv-patterns.md +161 -0
  178. package/bundled/manifest.json +1 -1
  179. package/package.json +1 -1
@@ -0,0 +1,780 @@
1
+ # SwiftUI View Structure Reference
2
+
3
+ ## Table of Contents
4
+
5
+ - [View Structure Principles](#view-structure-principles)
6
+ - [Recommended View File Structure](#recommended-view-file-structure)
7
+ - [Struct or Method / Computed Property?](#struct-or-method--computed-property)
8
+ - [Prefer Modifiers Over Conditional Views](#prefer-modifiers-over-conditional-views)
9
+ - [Extract Subviews, Not Computed Properties](#extract-subviews-not-computed-properties)
10
+ - [@ViewBuilder](#viewbuilder)
11
+ - [Keep View Body Simple and Avoid High-Cost Operations](#keep-view-body-simple-and-avoid-high-cost-operations)
12
+ - [When to Extract Subviews](#when-to-extract-subviews)
13
+ - [Container View Pattern](#container-view-pattern)
14
+ - [Utilize Lazy Containers for Large Data Sets](#utilize-lazy-containers-for-large-data-sets)
15
+ - [ZStack vs overlay/background](#zstack-vs-overlaybackground)
16
+ - [Compositing Group Before Clipping](#compositing-group-before-clipping)
17
+ - [Split State-Driven Parts into Custom View Types](#split-state-driven-parts-into-custom-view-types)
18
+ - [Reusable Styling with ViewModifier](#reusable-styling-with-viewmodifier)
19
+ - [Skeleton Loading with Redacted Views](#skeleton-loading-with-redacted-views)
20
+ - [AnyView](#anyview)
21
+ - [UIViewRepresentable Essentials](#uiviewrepresentable-essentials)
22
+ - [Troubleshooting](#troubleshooting)
23
+ - [Summary Checklist](#summary-checklist)
24
+
25
+ ## View Structure Principles
26
+
27
+ SwiftUI's diffing algorithm compares view hierarchies to determine what needs updating. Proper view composition directly impacts performance.
28
+
29
+ ## Recommended View File Structure
30
+
31
+ Use a consistent order when declaring SwiftUI views:
32
+
33
+ 1. Environment Properties
34
+ 2. State Properties
35
+ 3. Private Properties
36
+ 4. Initializer (if needed)
37
+ 5. Body
38
+ 6. Computed Properties/Methods for Subviews
39
+
40
+ ```swift
41
+ struct ContentView: View {
42
+ // MARK: - Environment Properties
43
+ @Environment(\.colorScheme) var colorScheme
44
+
45
+ // MARK: - State Properties
46
+ @Binding var isToggled: Bool
47
+ @State private var viewModel: SomeViewModel
48
+
49
+ // MARK: - Private Properties
50
+ private let title: String = "SwiftUI Guide"
51
+
52
+ // MARK: - Initializer (if needed)
53
+ init(isToggled: Binding<Bool>) {
54
+ self._isToggled = isToggled
55
+ }
56
+
57
+ // MARK: - Body
58
+ var body: some View {
59
+ VStack {
60
+ header
61
+ content
62
+ }
63
+ }
64
+
65
+ // MARK: - Computed Subviews
66
+ private var header: some View {
67
+ Text(title).font(.largeTitle).padding()
68
+ }
69
+
70
+ private var content: some View {
71
+ VStack {
72
+ Text("Counter: \(counter)")
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ## Struct or Method / Computed Property?
79
+
80
+ If a `View` is intended to be reusable across multiple screens, encapsulate it within a separate `struct`. If its usage is confined to a single context, it can be declared as a function or computed property within the containing `View`.
81
+
82
+ However, if a view maintains state using `@State`, `@Binding`, `@ObservedObject`, `@Environment`, `@StateObject`, or similar wrappers, it should generally be a separate `struct`.
83
+
84
+ - For simple, static views: a computed property is acceptable.
85
+ - For views requiring parameters: a method is more appropriate, but only when those parameters are stable. If parameters change per-call (e.g. inside a `ForEach` where each call receives a different item), prefer a separate `struct` so SwiftUI can diff inputs and skip body evaluation.
86
+ - For reusable, stateful, or logically independent UI sections: prefer a dedicated `struct`.
87
+
88
+ ```swift
89
+ struct ContentView: View {
90
+ var titleView: some View {
91
+ Text("Hello from Property")
92
+ .font(.largeTitle)
93
+ .foregroundColor(.blue)
94
+ }
95
+
96
+ func messageView(text: String, color: Color) -> some View {
97
+ Text(text)
98
+ .font(.title)
99
+ .foregroundColor(color)
100
+ .padding()
101
+ }
102
+
103
+ var body: some View {
104
+ VStack {
105
+ titleView
106
+ messageView(text: "Hello from Method", color: .red)
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ ## Prefer Modifiers Over Conditional Views
113
+
114
+ **Prefer "no-effect" modifiers over conditionally including views.** When you introduce a branch, consider whether you're representing multiple views or two states of the same view.
115
+
116
+ ### Use Opacity Instead of Conditional Inclusion
117
+
118
+ ```swift
119
+ // Good - same view, different states
120
+ SomeView()
121
+ .opacity(isVisible ? 1 : 0)
122
+
123
+ // Avoid - creates/destroys view identity
124
+ if isVisible {
125
+ SomeView()
126
+ }
127
+ ```
128
+
129
+ **Why**: Conditional view inclusion can cause loss of state, poor animation performance, and breaks view identity. Using modifiers maintains view identity across state changes.
130
+
131
+ ### When Conditionals Are Appropriate
132
+
133
+ Use conditionals when you truly have **different views**, not different states:
134
+
135
+ ```swift
136
+ // Correct - fundamentally different views
137
+ if isLoggedIn {
138
+ DashboardView()
139
+ } else {
140
+ LoginView()
141
+ }
142
+
143
+ // Correct - optional content
144
+ if let user {
145
+ UserProfileView(user: user)
146
+ }
147
+ ```
148
+
149
+ ### Conditional View Modifier Extensions Break Identity
150
+
151
+ A common pattern is an `if`-based `View` extension for conditional modifiers. This changes the view's return type between branches, which destroys view identity and breaks animations:
152
+
153
+ ```swift
154
+ // Problematic -- different return types per branch
155
+ extension View {
156
+ @ViewBuilder func `if`<T: View>(_ condition: Bool, transform: (Self) -> T) -> some View {
157
+ if condition {
158
+ transform(self) // Returns T
159
+ } else {
160
+ self // Returns Self
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ Prefer applying the modifier directly with a ternary or always-present modifier:
167
+
168
+ ```swift
169
+ // Good -- same view identity maintained
170
+ Text("Hello")
171
+ .opacity(isHighlighted ? 1 : 0.5)
172
+
173
+ // Good -- modifier always present, value changes
174
+ Text("Hello")
175
+ .foregroundStyle(isError ? .red : .primary)
176
+ ```
177
+
178
+ ## Extract Subviews, Not Computed Properties
179
+
180
+ ### The Problem with @ViewBuilder Functions
181
+
182
+ When you use `@ViewBuilder` functions or computed properties for complex views, the entire function re-executes on every parent state change:
183
+
184
+ ```swift
185
+ // BAD - re-executes complexSection() on every tap
186
+ struct ParentView: View {
187
+ @State private var count = 0
188
+
189
+ var body: some View {
190
+ VStack {
191
+ Button("Tap: \(count)") { count += 1 }
192
+ complexSection() // Re-executes every tap!
193
+ }
194
+ }
195
+
196
+ @ViewBuilder
197
+ func complexSection() -> some View {
198
+ // Complex views that re-execute unnecessarily
199
+ ForEach(0..<100) { i in
200
+ HStack {
201
+ Image(systemName: "star")
202
+ Text("Item \(i)")
203
+ Spacer()
204
+ Text("Detail")
205
+ }
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ ### The Solution: Separate Structs
212
+
213
+ Extract to separate `struct` views. SwiftUI can skip their `body` when inputs don't change:
214
+
215
+ ```swift
216
+ // GOOD - ComplexSection body SKIPPED when its inputs don't change
217
+ struct ParentView: View {
218
+ @State private var count = 0
219
+
220
+ var body: some View {
221
+ VStack {
222
+ Button("Tap: \(count)") { count += 1 }
223
+ ComplexSection() // Body skipped during re-evaluation
224
+ }
225
+ }
226
+ }
227
+
228
+ struct ComplexSection: View {
229
+ var body: some View {
230
+ ForEach(0..<100) { i in
231
+ HStack {
232
+ Image(systemName: "star")
233
+ Text("Item \(i)")
234
+ Spacer()
235
+ Text("Detail")
236
+ }
237
+ }
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### Why This Works
243
+
244
+ 1. SwiftUI compares the `ComplexSection` struct (which has no properties)
245
+ 2. Since nothing changed, SwiftUI skips calling `ComplexSection.body`
246
+ 3. The complex view code never executes unnecessarily
247
+
248
+ ## @ViewBuilder
249
+
250
+ Use `@ViewBuilder` functions for small, simple sections (a few views, no expensive computation) that don't affect performance. They work particularly well for static content that doesn't depend on any `@State` or `@Binding`, since SwiftUI won't need to diff them independently. Extract to a separate `struct` when the section is complex, depends on state, or needs to be skipped during re-evaluation.
251
+
252
+ The `@ViewBuilder` attribute is only required when a function or computed property returns multiple different views conditionally, for example through `if` or `switch`:
253
+
254
+ ```swift
255
+ @ViewBuilder
256
+ private var conditionalView: some View {
257
+ if isExpanded {
258
+ VStack {
259
+ Text("Expanded View")
260
+ Image(systemName: "star")
261
+ }
262
+ } else {
263
+ Text("Collapsed View")
264
+ }
265
+ }
266
+ ```
267
+
268
+ If every branch returns the same concrete type, `@ViewBuilder` is unnecessary:
269
+
270
+ ```swift
271
+ var conditionalText: some View {
272
+ if Bool.random() {
273
+ Text("Hello")
274
+ } else {
275
+ Text("World")
276
+ }
277
+ }
278
+ ```
279
+
280
+ Prefer `@ViewBuilder` when:
281
+
282
+ - there is conditional branching between multiple view types
283
+ - extracting a separate `struct` would not provide meaningful separation
284
+
285
+ ## Keep View Body Simple and Avoid High-Cost Operations
286
+
287
+ Refrain from performing complex operations within the `body` of your view. Instead of passing a ready-to-use sequence with filtering, mapping, or sorting directly into `ForEach`, prepare the sequence outside the body.
288
+
289
+ ```swift
290
+ // Avoid such things ...
291
+ var body: some View {
292
+ List {
293
+ ForEach(model.values.filter { $0 > 0 }, id: \.self) {
294
+ Text(String($0))
295
+ .padding()
296
+ }
297
+ }
298
+ }
299
+ ```
300
+
301
+ Prefer:
302
+
303
+ ```swift
304
+ struct FilteredListView: View {
305
+ private let filteredValues: [Int]
306
+
307
+ init(values: [Int]) {
308
+ self.filteredValues = values.filter { $0 > 0 } // Perform filtering once
309
+ }
310
+
311
+ var body: some View {
312
+ List {
313
+ content
314
+ }
315
+ }
316
+
317
+ private var content: some View {
318
+ ForEach(filteredValues, id: \.self) { value in
319
+ Text(String(value))
320
+ .padding()
321
+ }
322
+ }
323
+ }
324
+ ```
325
+
326
+ The reason this matters is that the system can call `body` multiple times during a single layout phase. Complex body computation makes those calls more expensive than necessary.
327
+
328
+ General guidance:
329
+
330
+ - avoid filtering, sorting, and mapping inline in `body`
331
+ - avoid constructing expensive formatters in `body`
332
+ - avoid heavy branching in large view trees
333
+ - move data preparation into init, model layer, or dedicated helpers
334
+
335
+ ## When to Extract Subviews
336
+
337
+ Extract complex views into separate subviews when:
338
+ - The view has multiple logical sections or responsibilities
339
+ - The view contains reusable components
340
+ - The view body becomes difficult to read or understand
341
+ - You need to isolate state changes for performance
342
+ - The view is becoming large (keep views small for better performance)
343
+ - The section may evolve independently over time
344
+
345
+ ## Container View Pattern
346
+
347
+ ### Avoid Closure-Based Content
348
+
349
+ Closures can't be compared, causing unnecessary re-renders:
350
+
351
+ ```swift
352
+ // BAD - closure prevents SwiftUI from skipping updates
353
+ struct MyContainer<Content: View>: View {
354
+ let content: () -> Content
355
+
356
+ var body: some View {
357
+ VStack {
358
+ Text("Header")
359
+ content() // Always called, can't compare closures
360
+ }
361
+ }
362
+ }
363
+
364
+ // Usage forces re-render on every parent update
365
+ MyContainer {
366
+ ExpensiveView()
367
+ }
368
+ ```
369
+
370
+ ### Use @ViewBuilder Property Instead
371
+
372
+ ```swift
373
+ // GOOD - view can be compared
374
+ struct MyContainer<Content: View>: View {
375
+ @ViewBuilder let content: Content
376
+
377
+ var body: some View {
378
+ VStack {
379
+ Text("Header")
380
+ content // SwiftUI can compare and skip if unchanged
381
+ }
382
+ }
383
+ }
384
+
385
+ // Usage - SwiftUI can diff ExpensiveView
386
+ MyContainer {
387
+ ExpensiveView()
388
+ }
389
+ ```
390
+
391
+ ## Utilize Lazy Containers for Large Data Sets
392
+
393
+ When displaying extensive lists or grids, prefer `LazyVStack`, `LazyHStack`, `LazyVGrid`, or `LazyHGrid`. These containers load views only when they appear on the screen, reducing memory usage and improving performance.
394
+
395
+ ```swift
396
+ struct ContentView: View {
397
+ let items = Array(0..<1000)
398
+
399
+ var body: some View {
400
+ ScrollView {
401
+ LazyVStack {
402
+ ForEach(items, id: \.self) { item in
403
+ Text("Item \(item)")
404
+ }
405
+ }
406
+ }
407
+ }
408
+ }
409
+ ```
410
+
411
+ Prefer lazy containers when:
412
+
413
+ - rendering large collections
414
+ - row views are non-trivial
415
+ - memory usage matters
416
+ - the content is inside `ScrollView`
417
+
418
+ ## ZStack vs overlay/background
419
+
420
+ Use `ZStack` to **compose multiple peer views** that should be layered together and jointly define layout.
421
+
422
+ Prefer `overlay` / `background` when you’re **decorating a primary view**.
423
+ Not primarily because they don’t affect layout size, but because they **express intent and improve readability**: the view being modified remains the clear layout anchor.
424
+
425
+ A key difference is **size proposal behavior**:
426
+ - In `overlay` / `background`, the child view implicitly adopts the size proposed to the parent when it doesn’t define its own size, making decorative attachments feel natural and predictable.
427
+ - In `ZStack`, each child participates independently in layout, and no implicit size inheritance exists. This makes it better suited for peer composition, but less intuitive for simple decoration.
428
+
429
+ Use `ZStack` (or another container) when the “decoration” **must explicitly participate in layout sizing**—for example, when reserving space, extending tappable/visible bounds, or preventing overlap with neighboring views.
430
+
431
+ ### Examples
432
+
433
+ ```swift
434
+ // GOOD - decoration via overlay (layout anchored to button)
435
+ Button("Continue") { }
436
+ .overlay(alignment: .trailing) {
437
+ Image(systemName: "lock.fill").padding(.trailing, 8)
438
+ }
439
+
440
+ // BAD - ZStack when overlay suffices (layout no longer anchored to button)
441
+ ZStack(alignment: .trailing) {
442
+ Button("Continue") { }
443
+ Image(systemName: "lock.fill").padding(.trailing, 8)
444
+ }
445
+
446
+ // GOOD - background shape takes parent size
447
+ HStack(spacing: 12) { Text("Inbox"); Text("Next") }
448
+ .background { Capsule().strokeBorder(.blue, lineWidth: 2) }
449
+ ```
450
+
451
+ ## Compositing Group Before Clipping
452
+
453
+ **Always add `.compositingGroup()` before `.clipShape()` when clipping layered views (`.overlay` or `.background`).** Without it, each layer is antialiased separately and then composited. Where antialiased edges overlap — typically at rounded corners — you get visible color fringes (semi-transparent pixels of different colors blending together).
454
+
455
+ ```swift
456
+ let shape = RoundedRectangle(cornerRadius: 16)
457
+
458
+ // BAD - each layer antialiased separately, producing color fringes at corners
459
+ Color.red
460
+ .overlay(.white, in: shape)
461
+ .clipShape(shape)
462
+ .frame(width: 200, height: 150)
463
+
464
+ // GOOD - layers composited first, antialiasing applied once during clipping
465
+ Color.red
466
+ .overlay(.white, in: .rect)
467
+ .compositingGroup()
468
+ .clipShape(shape)
469
+ .frame(width: 200, height: 150)
470
+ ```
471
+
472
+ `.compositingGroup()` forces all child layers to be rendered into a single offscreen buffer before the clip is applied. This means antialiasing only happens once — on the final composited result — eliminating the fringe artifacts.
473
+
474
+ ## Split State-Driven Parts into Custom View Types
475
+
476
+ Large views often depend on multiple independent state sources. If a single view body depends on all of them, then any state change can cause the entire body to re-evaluate.
477
+
478
+ ```swift
479
+ struct BigAndComplicatedView: View {
480
+ @State private var counter = 0
481
+ @State private var isToggled = false
482
+ @StateObject private var viewModel = SomeViewModel()
483
+
484
+ let title = "Big and Complicated View"
485
+
486
+ var body: some View {
487
+ VStack {
488
+ Text(title)
489
+ .font(.largeTitle)
490
+
491
+ Text("Counter: \(counter)")
492
+ .font(.title)
493
+
494
+ Toggle("Enable Feature", isOn: $isToggled)
495
+ .padding()
496
+
497
+ Button("Increment Counter") {
498
+ counter += 1
499
+ }
500
+
501
+ Text("ViewModel Data: \(viewModel.data)")
502
+ .padding()
503
+
504
+ Button("Fetch Data") {
505
+ viewModel.fetchData()
506
+ }
507
+ }
508
+ }
509
+ }
510
+ ```
511
+
512
+ ### Better: Split Into Smaller Components
513
+
514
+ ```swift
515
+ struct BigAndComplicatedView: View {
516
+ @State private var counter = 0
517
+ @State private var isToggled = false
518
+ @StateObject private var viewModel = SomeViewModel()
519
+
520
+ var body: some View {
521
+ VStack {
522
+ titleView
523
+ CounterView(counter: $counter)
524
+ ToggleView(isToggled: $isToggled)
525
+ ViewModelDataView(data: viewModel.data) {
526
+ viewModel.updateData()
527
+ }
528
+ .equatable()
529
+ }
530
+ }
531
+
532
+ private var titleView: some View {
533
+ Text("Big and Complicated View")
534
+ .font(.largeTitle)
535
+ }
536
+ }
537
+ ```
538
+
539
+ Why this is better:
540
+
541
+ - changing `counter` only affects `CounterView`
542
+ - toggling only affects `ToggleView`
543
+ - updating the model data only affects `ViewModelDataView`
544
+
545
+ ### Notes on Equatable
546
+
547
+ Using `Equatable` for a view is not a universal best practice, but it can be useful in targeted cases where:
548
+
549
+ - the input is small and well-defined
550
+ - the comparison logic is meaningful
551
+ - you want to reduce unnecessary body evaluation for a specific subtree
552
+
553
+ Do not use `Equatable` as a blanket optimization technique.
554
+
555
+ ## Reusable Styling with ViewModifier
556
+
557
+ Extract repeated modifier combinations into a `ViewModifier` struct. Expose via a `View` extension for autocompletion:
558
+
559
+ ```swift
560
+ private struct CardStyle: ViewModifier {
561
+ func body(content: Content) -> some View {
562
+ content
563
+ .padding()
564
+ .background(Color(.secondarySystemBackground))
565
+ .clipShape(.rect(cornerRadius: 12))
566
+ }
567
+ }
568
+
569
+ extension View {
570
+ func cardStyle() -> some View {
571
+ modifier(CardStyle())
572
+ }
573
+ }
574
+ ```
575
+
576
+ ### Custom ButtonStyle
577
+
578
+ Use the `ButtonStyle` protocol for reusable button designs. Use `PrimitiveButtonStyle` only when you need custom interaction handling (e.g., simultaneous gestures):
579
+
580
+ ```swift
581
+ struct PrimaryButtonStyle: ButtonStyle {
582
+ func makeBody(configuration: Configuration) -> some View {
583
+ configuration.label
584
+ .bold()
585
+ .foregroundStyle(.white)
586
+ .padding(.horizontal, 16)
587
+ .padding(.vertical, 8)
588
+ .background(Color.accentColor)
589
+ .clipShape(Capsule())
590
+ .scaleEffect(configuration.isPressed ? 0.95 : 1)
591
+ .animation(.smooth, value: configuration.isPressed)
592
+ }
593
+ }
594
+ ```
595
+
596
+ ### Discoverability with Static Member Lookup
597
+
598
+ Make custom styles and modifiers discoverable via leading-dot syntax:
599
+
600
+ ```swift
601
+ extension ButtonStyle where Self == PrimaryButtonStyle {
602
+ static var primary: PrimaryButtonStyle { .init() }
603
+ }
604
+
605
+ // Usage: .buttonStyle(.primary)
606
+ ```
607
+
608
+ This pattern works for any SwiftUI style protocol (`ButtonStyle`, `ListStyle`, `ToggleStyle`, etc.).
609
+
610
+ ## Skeleton Loading with Redacted Views
611
+
612
+ Use `.redacted(reason: .placeholder)` to show skeleton views while data loads. Use `.unredacted()` to opt out specific views:
613
+
614
+ ```swift
615
+ VStack(alignment: .leading) {
616
+ Text(article?.title ?? String(repeating: "X", count: 20))
617
+ .font(.headline)
618
+ Text(article?.author ?? String(repeating: "X", count: 12))
619
+ .font(.subheadline)
620
+ Text("SwiftLee")
621
+ .font(.caption)
622
+ .unredacted()
623
+ }
624
+ .redacted(reason: article == nil ? .placeholder : [])
625
+ ```
626
+
627
+ Apply `.redacted` on a container to redact all children at once.
628
+
629
+ ## AnyView
630
+
631
+ `AnyView` is type erasure. SwiftUI uses structural identity based on type information to determine when views should be updated.
632
+
633
+ ```swift
634
+ private var nameView: some View {
635
+ if isEditable {
636
+ TextField("Your name", text: $name)
637
+ } else {
638
+ Text(name)
639
+ }
640
+ }
641
+ ```
642
+
643
+ Avoid patterns like:
644
+
645
+ ```swift
646
+ private var nameView: some View {
647
+ if isEditable {
648
+ return AnyView(TextField("Your name", text: $name))
649
+ } else {
650
+ return AnyView(Text(name))
651
+ }
652
+ }
653
+ ```
654
+
655
+ Because `AnyView` erases type information, SwiftUI loses some optimization opportunities. Prefer `@ViewBuilder` or conditional branches with concrete view types.
656
+
657
+ Use `AnyView` only when type erasure is truly necessary for API design.
658
+
659
+ ## UIViewRepresentable Essentials
660
+
661
+ When bridging UIKit views into SwiftUI:
662
+
663
+ - `makeUIView(context:)` is called **once** to create the UIKit view
664
+ - `updateUIView(_:context:)` is called on **every SwiftUI redraw** to sync state
665
+ - The representable struct itself is **recreated on every redraw** -- avoid heavy work in its init
666
+ - Use a `Coordinator` for delegate callbacks and two-way communication
667
+
668
+ ```swift
669
+ struct MapView: UIViewRepresentable {
670
+ let coordinate: CLLocationCoordinate2D
671
+
672
+ func makeUIView(context: Context) -> MKMapView {
673
+ let map = MKMapView()
674
+ map.delegate = context.coordinator
675
+ return map
676
+ }
677
+
678
+ func updateUIView(_ map: MKMapView, context: Context) {
679
+ map.setCenter(coordinate, animated: true)
680
+ }
681
+
682
+ func makeCoordinator() -> Coordinator { Coordinator() }
683
+
684
+ class Coordinator: NSObject, MKMapViewDelegate { }
685
+ }
686
+ ```
687
+
688
+ ## Troubleshooting
689
+
690
+ ### Debug SwiftUI Renderings
691
+
692
+ If it is needed to debug render cycles and read console output you can leverage the `_printChanges()` or `_logChanges()` methods on `View`. These methods print information about when the view is being evaluated and what changes are triggering updates. This can be very helpful when your view body is called multiple times and you want to know why.
693
+
694
+ ```swift
695
+ struct ContentView: View {
696
+ @State private var counter: Int = 99
697
+
698
+ init() {
699
+ print(Self.self, #function)
700
+ }
701
+
702
+ var body: some View {
703
+ let _ = Self._printChanges()
704
+
705
+ VStack {
706
+ Text("Counter: \(counter)")
707
+ Button {
708
+ counter += 1
709
+ } label: {
710
+ Text("Counter +1")
711
+ }
712
+ .buttonStyle(.borderedProminent)
713
+ }
714
+ .padding()
715
+ }
716
+ }
717
+ ```
718
+
719
+ As an alternative to `Self._printChanges()`, you can use `_logChanges()`
720
+
721
+ ```swift
722
+ struct ContentView: View {
723
+ @State private var counter: Int = 99
724
+
725
+ var body: some View {
726
+ let _ = Self._logChanges()
727
+
728
+ VStack {
729
+ Text("Counter: \(counter)")
730
+ Button {
731
+ counter += 1
732
+ } label: {
733
+ Text("Counter +1")
734
+ }
735
+ .buttonStyle(.borderedProminent)
736
+ }
737
+ .padding()
738
+ }
739
+ }
740
+ ```
741
+
742
+ Use these tools only for debugging and remove them from production code.
743
+
744
+ ### Handling "The Compiler Is Unable to Type-Check This Expression in Reasonable Time"
745
+
746
+ If you encounter:
747
+
748
+ > The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
749
+
750
+ it is often caused by overly complex view structures or expressions.
751
+
752
+ Ways to fix it:
753
+
754
+ - break large expressions into smaller computed values
755
+ - extract subviews
756
+ - split long modifier chains
757
+ - simplify nested generics and builders
758
+ - avoid huge inline closures
759
+
760
+ ## Summary Checklist
761
+
762
+ - [ ] Follow a consistent view file structure (Environment → State → Private → Init → Body → Subviews)
763
+ - [ ] Prefer modifiers over conditional views for state changes
764
+ - [ ] Avoid `if`-based conditional modifier extensions (they break view identity)
765
+ - [ ] Extract complex views into separate subviews, not computed properties
766
+ - [ ] Keep views small for readability and performance
767
+ - [ ] Use `@ViewBuilder` only where it actually adds value
768
+ - [ ] Avoid heavy filtering, mapping, sorting, or formatter creation inside `body`
769
+ - [ ] Use lazy containers for large data sets
770
+ - [ ] Container views use `@ViewBuilder let content: Content`
771
+ - [ ] Prefer `overlay` / `background` for decoration and `ZStack` for peer composition
772
+ - [ ] `.compositingGroup()` before `.clipShape()` on layered views to avoid antialiasing fringes
773
+ - [ ] Split state-heavy areas into smaller view types
774
+ - [ ] Extract repeated styling into `ViewModifier` or `ButtonStyle`
775
+ - [ ] Expose reusable styles via static member lookup when it improves discoverability
776
+ - [ ] Use `.redacted(reason: .placeholder)` for loading skeletons
777
+ - [ ] Avoid `AnyView` unless type erasure is truly needed
778
+ - [ ] In `UIViewRepresentable`, keep heavy work out of struct init
779
+ - [ ] Use `_printChanges()` / `_logChanges()` to debug rendering behavior
780
+ - [ ] Break up overly complex expressions when the compiler struggles