mirror of
https://github.com/steipete/agent-rules.git
synced 2025-12-16 12:00:09 +01:00
- Reduce from 1085 lines to 89 lines (92% reduction) - Remove all scripts and verbose installation instructions - Reference GitHub repos for detailed descriptions - Keep only essential quick install commands - Trust that AI assistants are intelligent enough to figure things out - Focus on clear rules and a simple presentation template The new document: - States clear rules for AI assistants - Provides a presentation template - Lists quick install commands - References external docs for details - Assumes both user and AI are intelligent
165 lines
4.4 KiB
Plaintext
165 lines
4.4 KiB
Plaintext
# Modern Swift Development
|
|
|
|
Write idiomatic SwiftUI code following Apple's latest architectural recommendations and best practices.
|
|
|
|
## Core Philosophy
|
|
|
|
- SwiftUI is the default UI paradigm for Apple platforms - embrace its declarative nature
|
|
- Avoid legacy UIKit patterns and unnecessary abstractions
|
|
- Focus on simplicity, clarity, and native data flow
|
|
- Let SwiftUI handle the complexity - don't fight the framework
|
|
|
|
## Architecture Guidelines
|
|
|
|
### 1. Embrace Native State Management
|
|
|
|
Use SwiftUI's built-in property wrappers appropriately:
|
|
- `@State` - Local, ephemeral view state
|
|
- `@Binding` - Two-way data flow between views
|
|
- `@Observable` - Shared state (iOS 17+)
|
|
- `@ObservableObject` - Legacy shared state (pre-iOS 17)
|
|
- `@Environment` - Dependency injection for app-wide concerns
|
|
|
|
### 2. State Ownership Principles
|
|
|
|
- Views own their local state unless sharing is required
|
|
- State flows down, actions flow up
|
|
- Keep state as close to where it's used as possible
|
|
- Extract shared state only when multiple views need it
|
|
|
|
### 3. Modern Async Patterns
|
|
|
|
- Use `async/await` as the default for asynchronous operations
|
|
- Leverage `.task` modifier for lifecycle-aware async work
|
|
- Avoid Combine unless absolutely necessary
|
|
- Handle errors gracefully with try/catch
|
|
|
|
### 4. View Composition
|
|
|
|
- Build UI with small, focused views
|
|
- Extract reusable components naturally
|
|
- Use view modifiers to encapsulate common styling
|
|
- Prefer composition over inheritance
|
|
|
|
### 5. Code Organization
|
|
|
|
- Organize by feature, not by type (avoid Views/, Models/, ViewModels/ folders)
|
|
- Keep related code together in the same file when appropriate
|
|
- Use extensions to organize large files
|
|
- Follow Swift naming conventions consistently
|
|
|
|
## Implementation Patterns
|
|
|
|
### Simple State Example
|
|
```swift
|
|
struct CounterView: View {
|
|
@State private var count = 0
|
|
|
|
var body: some View {
|
|
VStack {
|
|
Text("Count: \(count)")
|
|
Button("Increment") {
|
|
count += 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Shared State with @Observable
|
|
```swift
|
|
@Observable
|
|
class UserSession {
|
|
var isAuthenticated = false
|
|
var currentUser: User?
|
|
|
|
func signIn(user: User) {
|
|
currentUser = user
|
|
isAuthenticated = true
|
|
}
|
|
}
|
|
|
|
struct MyApp: App {
|
|
@State private var session = UserSession()
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
ContentView()
|
|
.environment(session)
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Async Data Loading
|
|
```swift
|
|
struct ProfileView: View {
|
|
@State private var profile: Profile?
|
|
@State private var isLoading = false
|
|
@State private var error: Error?
|
|
|
|
var body: some View {
|
|
Group {
|
|
if isLoading {
|
|
ProgressView()
|
|
} else if let profile {
|
|
ProfileContent(profile: profile)
|
|
} else if let error {
|
|
ErrorView(error: error)
|
|
}
|
|
}
|
|
.task {
|
|
await loadProfile()
|
|
}
|
|
}
|
|
|
|
private func loadProfile() async {
|
|
isLoading = true
|
|
defer { isLoading = false }
|
|
|
|
do {
|
|
profile = try await ProfileService.fetch()
|
|
} catch {
|
|
self.error = error
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### DO:
|
|
- Write self-contained views when possible
|
|
- Use property wrappers as intended by Apple
|
|
- Test logic in isolation, preview UI visually
|
|
- Handle loading and error states explicitly
|
|
- Keep views focused on presentation
|
|
- Use Swift's type system for safety
|
|
|
|
### DON'T:
|
|
- Create ViewModels for every view
|
|
- Move state out of views unnecessarily
|
|
- Add abstraction layers without clear benefit
|
|
- Use Combine for simple async operations
|
|
- Fight SwiftUI's update mechanism
|
|
- Overcomplicate simple features
|
|
|
|
## Testing Strategy
|
|
|
|
- Unit test business logic and data transformations
|
|
- Use SwiftUI Previews for visual testing
|
|
- Test @Observable classes independently
|
|
- Keep tests simple and focused
|
|
- Don't sacrifice code clarity for testability
|
|
|
|
## Modern Swift Features
|
|
|
|
- Use Swift Concurrency (async/await, actors)
|
|
- Leverage Swift 6 data race safety when available
|
|
- Utilize property wrappers effectively
|
|
- Embrace value types where appropriate
|
|
- Use protocols for abstraction, not just for testing
|
|
|
|
## Summary
|
|
|
|
Write SwiftUI code that looks and feels like SwiftUI. The framework has matured significantly - trust its patterns and tools. Focus on solving user problems rather than implementing architectural patterns from other platforms. |