MVVM: Separate SwiftUI Logic from Layout

MVVM separates logic from layout by moving state and business logic out of your SwiftUI View into a dedicated ViewModel class. This makes your code cleaner, more organized, and easier to test.
Why it exists
SwiftUI views are structs, which is great for performance. But as apps grow, views can become bloated with state management, data fetching, and business logic. This makes them hard to read, maintain, and especially to test. MVVM provides a clear separation of concerns to solve this problem.
The mental model
Think of a View as just the "what" — what buttons, text, and images to show. The ViewModel is the "how" — how to fetch data, what happens when a button is tapped, and how to format data for display. The View is dumb; it just renders what the ViewModel gives it and tells the ViewModel about user actions.
How it works
In SwiftUI, you create an @Observable class to act as your ViewModel. You then move state properties (like @State variables) and related logic (like functions) from your View struct into this new class. The View then holds a single instance of its ViewModel. Instead of accessing its own properties, the View reads data from the ViewModel (e.g., viewModel.items) and calls its methods (e.g., viewModel.fetchItems()). When the ViewModel's properties change, the UI updates automatically.
When to use it
Use MVVM as soon as a view starts to feel complex. If you have multiple related @State properties, logic inside your body computed property, or need to fetch and manipulate data, it's time for a ViewModel. It is the standard pattern for most non-trivial SwiftUI applications.
When not to use it
For very simple, static views with little or no state, creating a ViewModel is overkill. If a view only displays data passed into it and has no internal logic, you don't need the extra layer. Some purely presentational UI state (like the isPresented flag for a sheet) can often stay in the view without issue.
One canonical example
A common practice is to define the ViewModel inside an extension of the view it serves, like extension ContentView { class ViewModel { ... } }. For a login screen, you'd move username and password properties and an authenticate() method into this ViewModel. The LoginView would then just have @State private var viewModel = ViewModel(), and its UI would bind to viewModel.username and call viewModel.authenticate(). This isolates all authentication logic, making it fully testable without any UI code.
Interview question
What is the primary advantage of implementing the MVVM pattern in a complex SwiftUI view?
- a.It automatically manages all UI state, eliminating the need for @State or @Binding in the view.
- b.It ensures all data fetching and persistence logic is handled exclusively by the ViewModel.
- c.It makes the view's business logic independently testable and keeps the view focused solely on UI presentation.Correct
- d.It allows the view to become a struct, which inherently improves SwiftUI's rendering efficiency.
Why? this is the answer
MVVM's core benefit is separating business logic from the UI, making the logic independently testable and simplifying the view's role to just rendering. While MVVM moves much of the state, purely presentational UI state can still reside in the view, so it doesn't eliminate all @State.
Just read this? Test yourself on what you have been reading.
Read the original → hackingwithswift.com
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on ios — each one lists the topics its interview covers.
See open roles