Signed-off-by: Matt Bruce <matt.bruce1@toyota.com>

This commit is contained in:
Matt Bruce 2026-02-11 13:22:51 -06:00
parent 88e4402d38
commit f3dd8d92bd
4 changed files with 26 additions and 46 deletions

View File

@ -8,13 +8,9 @@ globs: ["**/*.swift", "**/*.xcstrings"]
Use **String Catalogs** (`.xcstrings` files) for localization in modern Swift projects. Use **String Catalogs** (`.xcstrings` files) for localization in modern Swift projects.
## Required Language Support ## Language Support
At minimum, support these languages: 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.
- **English (en)** - Base language
- **Spanish - Mexico (es-MX)**
- **French - Canada (fr-CA)**
## How String Catalogs Work ## How String Catalogs Work

View File

@ -261,7 +261,9 @@ let result = largeArray
## Error Handling ## 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
// Swift 6 - Typed throws // Swift 6 - Typed throws

View File

@ -45,10 +45,7 @@ Each protocol should represent one capability (Interface Segregation Principle):
```swift ```swift
// GOOD - Focused protocols // GOOD - Focused protocols
protocol Identifiable { // Note: Swift provides Identifiable already — adopt it, don't redefine it.
var id: UUID { get }
}
protocol Nameable { protocol Nameable {
var displayName: String { get } var displayName: String { get }
} }
@ -58,8 +55,13 @@ protocol Timestamped {
var updatedAt: Date { get } var updatedAt: Date { get }
} }
// Compose as needed // Compose as needed (Identifiable comes from Swift standard library)
struct User: Identifiable, Nameable, Timestamped { ... } struct User: Identifiable, Nameable, Timestamped {
let id: UUID
var displayName: String
var createdAt: Date
var updatedAt: Date
}
``` ```
```swift ```swift

View File

@ -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 ## Observable Pattern
### Use @Observable Not ObservableObject ### Use @Observable Not ObservableObject
@ -294,24 +266,32 @@ func makeView(for type: ViewType) -> some View {
## Lists and ForEach ## 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 ```swift
// BAD - Unnecessary Array conversion // BAD - offset-based id breaks animations when items change
ForEach(Array(items.enumerated()), id: \.offset) { index, item in 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 ForEach(items.indices, id: \.self) { index in
let item = items[index] let item = items[index]
// ... // ...
} }
// GOOD - If you need both // GOOD - Identifiable items work directly (protocol-based)
ForEach(Array(zip(items.indices, items)), id: \.0) { index, item in 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 ### Hide Scroll Indicators