diff --git a/assets/skills/swift-localization/SKILL.md b/assets/skills/swift-localization/SKILL.md index 8d057a1..63f7544 100644 --- a/assets/skills/swift-localization/SKILL.md +++ b/assets/skills/swift-localization/SKILL.md @@ -8,13 +8,9 @@ globs: ["**/*.swift", "**/*.xcstrings"] Use **String Catalogs** (`.xcstrings` files) for localization in modern Swift projects. -## Required Language Support +## Language Support -At minimum, support these languages: - -- **English (en)** - Base language -- **Spanish - Mexico (es-MX)** -- **French - Canada (fr-CA)** +At minimum, support the base development language (typically English). Add additional locales based on your app's target markets. Common additions include Spanish and French variants. ## How String Catalogs Work diff --git a/assets/skills/swift-modern/SKILL.md b/assets/skills/swift-modern/SKILL.md index c4c998d..1b7abb3 100644 --- a/assets/skills/swift-modern/SKILL.md +++ b/assets/skills/swift-modern/SKILL.md @@ -261,7 +261,9 @@ let result = largeArray ## Error Handling -### Prefer Typed Throws (Swift 6) +### Prefer Typed Throws (Swift 6 / Xcode 16+) + +Typed throws requires the **Swift 6 compiler** (shipped with Xcode 16). The feature works at any deployment target, but your project must compile with Swift 6. If your team hasn't migrated yet, continue using untyped `throws`. ```swift // Swift 6 - Typed throws diff --git a/assets/skills/swift-pop/SKILL.md b/assets/skills/swift-pop/SKILL.md index ff614ed..c9207fe 100644 --- a/assets/skills/swift-pop/SKILL.md +++ b/assets/skills/swift-pop/SKILL.md @@ -45,10 +45,7 @@ Each protocol should represent one capability (Interface Segregation Principle): ```swift // GOOD - Focused protocols -protocol Identifiable { - var id: UUID { get } -} - +// Note: Swift provides Identifiable already — adopt it, don't redefine it. protocol Nameable { var displayName: String { get } } @@ -58,8 +55,13 @@ protocol Timestamped { var updatedAt: Date { get } } -// Compose as needed -struct User: Identifiable, Nameable, Timestamped { ... } +// Compose as needed (Identifiable comes from Swift standard library) +struct User: Identifiable, Nameable, Timestamped { + let id: UUID + var displayName: String + var createdAt: Date + var updatedAt: Date +} ``` ```swift diff --git a/assets/skills/swiftui-modern/SKILL.md b/assets/skills/swiftui-modern/SKILL.md index 7786a92..408ae10 100644 --- a/assets/skills/swiftui-modern/SKILL.md +++ b/assets/skills/swiftui-modern/SKILL.md @@ -99,34 +99,6 @@ final class NavigationStore { } ``` -## Tab View - -### Use Tab API Not tabItem() - -```swift -// BAD - Old tabItem pattern -TabView { - HomeView() - .tabItem { - Label("Home", systemImage: "house") - } - SettingsView() - .tabItem { - Label("Settings", systemImage: "gear") - } -} - -// GOOD - Tab API (iOS 18+) -TabView { - Tab("Home", systemImage: "house") { - HomeView() - } - Tab("Settings", systemImage: "gear") { - SettingsView() - } -} -``` - ## Observable Pattern ### Use @Observable Not ObservableObject @@ -294,24 +266,32 @@ func makeView(for type: ViewType) -> some View { ## Lists and ForEach -### Don't Convert to Array for Enumeration +### Use Identifiable Conformance for ForEach + +Let `ForEach` use `Identifiable` conformance directly — don't bypass it with manual key paths or offset-based identity. ```swift -// BAD - Unnecessary Array conversion +// BAD - offset-based id breaks animations when items change ForEach(Array(items.enumerated()), id: \.offset) { index, item in // ... } -// GOOD - Use indices or zip +// BAD - index-based id has the same animation problem ForEach(items.indices, id: \.self) { index in let item = items[index] // ... } -// GOOD - If you need both -ForEach(Array(zip(items.indices, items)), id: \.0) { index, item in +// GOOD - Identifiable items work directly (protocol-based) +ForEach(items) { item in // ... } + +// GOOD - When index is also needed, use enumerated keyed on the item's identity +ForEach(Array(items.enumerated()), id: \.element.id) { index, item in + // Stable identity comes from item.id (Identifiable conformance), + // not from the offset — so animations and diffing work correctly. +} ``` ### Hide Scroll Indicators