The View in MVVM
The View in MVVM is the layer responsible for rendering the UI and capturing raw user input, and in a well-structured MVVM app it is deliberately kept as 'dumb' as possible: it declares what should appear on screen and which ViewModel properties or commands each control is bound to, but it contains no business logic and makes no decisions about what data means. In frameworks like SwiftUI, Jetpack Compose, and WPF/XAML, the View is often declarative markup or a declarative function that describes the UI as a function of state, which pairs naturally with the ViewModel's observable properties.
Cricket analogy: A stadium's digital scoreboard is a pure View: it displays whatever numbers the official scoring system sends it, with the board itself making no judgment calls about whether a delivery was a no-ball.
Responsibilities of the View
Concretely, the View's job is threefold: render the current state by binding controls to ViewModel properties (a Text element bound to viewModel.username), forward raw user gestures to the ViewModel as commands (a Button's action calling viewModel.submitTapped() rather than containing submission logic itself), and handle purely visual, non-business concerns like animations, transitions, layout, and platform-specific styling such as safe-area insets or dark-mode color adaptation. The View should never call a repository, never talk to a network client, and never contain a branch like 'if user.role == admin' that encodes a business rule — that decision belongs in the ViewModel, exposed as something like viewModel.isAdminSectionVisible.
Cricket analogy: A broadcast graphics operator's console lets them trigger a 'replay' animation on cue, but the decision of whether a dismissal was out came from the third umpire's review system, not from the graphics operator's own judgment.
// SwiftUI View: purely declarative, binds to ViewModel, no business logic
struct LoginView: View {
@StateObject private var viewModel = LoginViewModel()
var body: some View {
VStack(spacing: 16) {
TextField("Username", text: $viewModel.username)
.textFieldStyle(.roundedBorder)
if let error = viewModel.errorMessage {
Text(error)
.foregroundColor(.red)
.transition(.opacity)
}
Button("Log In") {
viewModel.submitTapped()
}
.disabled(!viewModel.canLogin)
}
.animation(.easeInOut, value: viewModel.errorMessage)
.padding()
}
}Declarative UI frameworks like SwiftUI, Jetpack Compose, and Flutter are a particularly natural fit for MVVM because the View is literally written as a function from state to UI — body or Composable re-executes whenever bound ViewModel state changes — which mirrors MVVM's philosophy far more directly than older imperative UI toolkits where you manually called label.setText(...).
View and Lifecycle
Views have platform-specific lifecycle events — appear/disappear in SwiftUI, onCreate/onResume/onPause in Android Activities, componentDidMount in older React class components — and the View's role is to forward those lifecycle moments to the ViewModel (for example, calling viewModel.onAppear() from .onAppear {}) so the ViewModel can decide what to do, such as starting a data refresh or subscribing to a live feed, rather than the View making that decision itself. This keeps lifecycle-triggered business logic testable, since the ViewModel's onAppear() method can be called directly in a unit test without simulating an actual screen transition.
Cricket analogy: When a viewer opens the live-match app (View 'appears'), the app notifies the match-data ViewModel to start polling the live feed, rather than the screen itself deciding to fetch data.
Never have a ViewModel hold a direct reference to a View type (like a UIViewController, Activity, or SwiftUI View struct) to call UI methods on it — this breaks the whole point of MVVM by re-coupling the ViewModel to a specific UI implementation, makes the ViewModel untestable without that UI framework, and typically causes memory leaks from retained View references. If the ViewModel needs to trigger a one-off effect like navigation, use an event stream or a delegate/callback the View subscribes to, not a stored View reference.
- The View renders UI and captures raw user input, staying as free of business logic as possible.
- The View binds controls to ViewModel properties and forwards user gestures as ViewModel commands.
- Purely visual concerns like animation, transitions, and platform styling belong to the View.
- Declarative frameworks like SwiftUI, Compose, and Flutter fit MVVM naturally since the View is a function of state.
- The View forwards lifecycle events (appear, resume, mount) to the ViewModel rather than acting on them itself.
- Forwarding lifecycle events keeps business logic in the ViewModel testable without simulating screen transitions.
- Never let a ViewModel hold a direct reference to a concrete View type; use events or callbacks instead.
Practice what you learned
1. What should a Button's tap handler typically do in a well-structured MVVM View?
2. Which of the following is an appropriate View-layer responsibility?
3. Why do declarative UI frameworks like SwiftUI and Jetpack Compose pair naturally with MVVM?
4. What is the danger of a ViewModel holding a direct reference to a concrete View type?
Was this page helpful?
You May Also Like
What Is MVVM?
An introduction to the Model-View-ViewModel pattern and how data binding connects its three layers.
The ViewModel in MVVM
How the ViewModel exposes observable state and commands, manages lifecycle, and stays independently testable.
The Model in MVVM
What belongs in the Model layer of MVVM, how it differs from ViewModel state, and how to test it.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics