Insights / iOS Architecture
SwiftUI Architecture Patterns for AI-Native iOS Apps in 2026
According to the 2024 State of Swift Developer Survey, SwiftUI is now the primary UI framework for over 58% of new iOS codebases — up from 34% in 2022. The architecture question is no longer whether to use SwiftUI. It's how to structure it for apps that also need to run on-device AI.
The three patterns in production use
Most SwiftUI production codebases today use one of three architectural approaches. Each has a legitimate context where it wins — and a common context where teams choose it for the wrong reasons.
| Pattern | State model | Boilerplate | Testability |
|---|---|---|---|
| MVVM + @Observable | Observable class per screen | Low | High |
| TCA | Reducer + State + Action | High | Very High |
| Observation + Environment | Shared @Observable injected via environment | Low | Medium |
MVVM with Swift Observation — the 2026 default
Apple's Observation framework (introduced in iOS 17) made MVVM significantly leaner. The @Observable macro replaces the manual ObservableObject + @Published boilerplate and provides automatic fine-grained tracking — SwiftUI only re-renders the views that read a specific property when that property changes.
A production MVVM view model with @Observable looks like this:
@Observable
final class ImageClassifierViewModel {
var result: ClassificationResult? = nil
var isLoading: Bool = false
var error: Error? = nil
private let classifier: ImageClassifierActor
init(classifier: ImageClassifierActor) {
self.classifier = classifier
}
func classify(_ image: CGImage) {
isLoading = true
error = nil
Task {
do {
result = try await classifier.predict(image)
} catch {
self.error = error
}
isLoading = false
}
}
}The view model is simple to test — inject a mock ImageClassifierActor, call classify(), and assert on the published state. No view rendering required. The Actor layer handles thread safety for the ML model itself — described in the next section.
The Actor pattern for Core ML integration
Core ML's MLModel is not thread-safe. Calling prediction() concurrently from multiple threads can cause crashes or silent incorrect results. Swift Actors solve this at the language level: the actor serializes access to its internal state, making the model thread-safe by construction.
actor ImageClassifierActor {
private var model: ImageClassifier? = nil
func predict(_ image: CGImage) async throws -> ClassificationResult {
if model == nil {
model = try await ImageClassifier.load()
}
guard let model else { throw ClassifierError.modelUnavailable }
let input = try ImageClassifierInput(image: image)
let output = try model.prediction(input: input)
return ClassificationResult(output)
}
}Two details matter here. First, the model is loaded lazily inside the actor — not at app launch. Model loading can take 50–500ms and should never block the main thread or delay app startup. Second, the actor satisfies Swift's Sendable requirements automatically, so the compiler will catch any accidental unsafecrossing of the actor boundary.
Apple's WWDC 2023 session “Discover Observation in SwiftUI” covers how @Observable integrates with Swift Concurrency — worth watching if you are migrating existing ObservableObject-based view models.
When TCA is the right choice
The Composable Architecture (TCA) forces every state mutation through an explicit Action type processed by a Reducer. All state is a value type. Side effects are isolated to Effect. This guarantees unidirectional data flow with no exceptions — which pays off in three specific contexts:
- —Complex multi-step flows. Checkout, onboarding, and multi-page wizards with back-navigation and partial-completion states are significantly easier to reason about in TCA than in MVVM, where state can drift from multiple sources.
- —Large engineering teams. TCA's strict structure prevents accidental state mutations that become harder to track as the team grows. Every change goes through the same Reducer path.
- —Exhaustive testing requirements. TCA's
TestStoreallows you to assert on every state transition in sequence — a level of test coverage that's impossible with observable classes.
The trade-off is real. TCA adds approximately 40–60% more code for equivalent functionality compared to MVVM + Observation. For a 3-person startup building a focused productivity app, that overhead ships slower and teaches the team a framework-specific mental model instead of standard Swift patterns.
Architecture decision matrix
| Context | Recommended pattern |
|---|---|
| Startup MVP, 1–3 engineers, simple flows | MVVM + @Observable |
| App with on-device AI or Core ML inference | MVVM + @Observable + Actor |
| Complex multi-step flows with undo/redo | TCA |
| Large team (>5 engineers) needing strict conventions | TCA |
| Shared global state across many screens | Observation + Environment |
| iOS 16 compatibility required | MVVM + ObservableObject (no @Observable) |
Common architectural mistakes in SwiftUI apps
- 1.Business logic in views. SwiftUI views are an excellent rendering layer. They are a poor business logic container. Any logic that needs to be tested without rendering a view belongs in a view model or domain layer.
- 2.Singleton state managers. Global singletons for app-wide state feel convenient until you need to test components in isolation. Prefer dependency injection — pass view models and services explicitly, or inject via SwiftUI's environment.
- 3.Not designing for async state. Async operations — network calls, Core ML inference, SwiftData fetches — all produce loading, success, and error states. Designing views to handle all three states from the start results in significantly fewer production crashes than retrofitting error handling later.
- 4.Over-structuring early. Adding TCA or a custom module architecture to a project with one developer and one screen wastes time that should go toward shipping. Architecture is a response to real complexity — not a hedge against future complexity that may never arrive.
FAQ
Should I use MVVM or TCA for my SwiftUI app in 2026?↓
How should Core ML inference be integrated into a SwiftUI architecture?↓
Does @Observable replace Combine in SwiftUI apps?↓
What happens to my SwiftUI architecture when I add AI features?↓
Related reading
Need an architecture review for your iOS app?
The iOS Architecture Audit covers system design, SwiftUI state management, Core ML integration readiness, and a prioritized roadmap — delivered in 5 business days.
Apply for an Audit