When to activate
- Building iOS apps with SwiftUI
- Implementing async data loading with Swift Concurrency
- Persisting data with SwiftData or Core Data
- Integrating Apple frameworks (HealthKit, MapKit, WidgetKit)
- Preparing apps for App Store submission
When NOT to use
- For cross-platform apps (use react-native-expo or flutter-widgets)
- For Android-only development
- For macOS-only apps (different framework)
Instructions
- Project structure. MVVM: Views (SwiftUI) → ViewModels (@Observable) → Services (async/await) → Models (SwiftData).
- SwiftUI views. Keep views small and composable. Use
@Statefor local,@Bindablefor shared,@Environmentfor injected. - Async data.
async letfor parallel,Taskfor background work,.taskmodifier for view lifecycle. Handle loading/error states explicitly. - SwiftData.
@Modelfor entities,@Queryfor fetching,ModelContainerfor setup. Migrate from Core Data only if benefits outweigh effort. - Navigation.
NavigationStackwith type-safeNavigationPath. Define routes as enums. Support deep linking viaonOpenURL. - Accessibility.
.accessibilityLabel,.accessibilityHint, Dynamic Type support with@ScaledMetric, VoiceOver testing. - Testing. XCTest for unit, XCUITest for UI, Snapshot tests for visual regression.
Example
@Observable
class ProductListViewModel {
var products: [Product] = []
var isLoading = false
var error: Error?
func loadProducts() async {
isLoading = true
defer { isLoading = false }
do {
products = try await api.fetchProducts()
} catch {
self.error = error
}
}
}
struct ProductListView: View {
@State private var viewModel = ProductListViewModel()
var body: some View {
NavigationStack {
List(viewModel.products) { product in
NavigationLink(value: product) {
ProductRow(product: product)
}
}
.task { await viewModel.loadProducts() }
}
}
}