When implementing a form with MVVM in SwiftUI, we end up having to deal with a lot of boilerplate code for our bindings.
Personally, I've been adopting TCA for my personal projects and as my main approach to SwiftUI views, but at work, there are some flows that the team decided to use MVVM. Being that, you can simplify things and avoid some boilerplate. To tackle this problem, I’ve come up with a solution inspired on a series from PointFree.co.
Simple / Common Form
The example above is very simple, and maybe won't help you to see what is the problems I'm trying to show, but allow yourself to extrapolate a little and think about a scenario with lots of validations and properties to the form…
In the extrapolated scenario, you would probably end up having to create lots of methods to set the form values, bindings to come along them, logic to check whether you can update the value or fire some other method, and so on...
But gladly, we can use a very interesting resource of Swift, called KeyPaths to reduce some of this boilerplate.
Of course, we could bind to the data directly using the shorthands $viewModel.state.email and $viewModel.state.password, but this would leave us with new problems. For example, when dealing with observation of state changes and it's side effects, like what happens on the updatePassword(_:) function.
Enter the StateBindingViewModel
Updating our initial code
With StateBindingViewModel, we are able to avoid the explicit creation of Binding's and remove some methods from the ViewModel, while improving the way we deal with changes to the state.
If we think again about our complex form scenario, the proposed solution would allow us to only have methods or cases to deal with specific KeyPath's instead on having to create setter's for everything. If we have no additional logic, we simply need the use the binding(_:) function and nothing else.