Advanced Toggle Switch in SwiftUI
Learn how to create and use a toggle and how to handle visual state changes when an error occurs
Introduction
Although SwiftUI is being developed more and more, many details useful in everyday work are still not obvious or even non-existent.
In such cases, it is often necessary to resort to alternative solutions that will solve our problem.
This situation also affects the Toggle
switch. Its basic implementation is quite obvious, but for the purposes of this article, let’s try to formalize it as closely as it should appear in the production code, on the example of a change in the status of GDPR consents.
Implementation
Let’s start with the implementation of the CustomToggle
structure with a title, subtitle, and toggle switch like this:
That’s a good start, now let’s create a view and a view model that will be responsible for displaying the Toggle
switch and handling the logic associated with it:
For the purposes of this article, viewModel
in the CustomView
as well as GdprAgreementsService
in the CustomViewModel
have not been injected, which is an obvious procedure in a production implementation. As you can see, the AnyPublisher
extension was also used here to get rid of the unnecessary in this case return value:
The last thing in the basic implementation is of course the GdprAgreementsService
already initialized in the view model:
Let us pause for a moment at this point. Why is the publisher saveAgreements (isGdprAccepted: Bool?)
value optional?
This procedure (for the purposes of the article) allows you to easily simulate an error in the saveGdprState (state :)
method and reveal a Toggle
switch state error, because even if the user changes isOn
state to true
, the agreements state will not be updated — so we have a discrepancy between the visible state for the user and the actual situation.
Of course, the same is true the other way around, when a user wishes to opt-out of having consented to tracking.
Solution
In order to prevent a discrepancy between the visual and actual state in the event of a fault, it must be possible to externally influence the toggle state of the switch.
It will be possible to separate it into two flags: isOn
, which will be responsible only for its state, and isPermissionGranted
for handling consents.
For this purpose, the implementation of the CustomToggle
view should be updated like this:
Now, thanks to the transfer of the isPermissionGranted
flag to the .onTapGesture
action, we can set the Toggle
switch state without modifying the consent.
We also need a small change to the CustomView
body:
…and a little more in the CustomViewModel
:
Voilà! Thanks to these modifications, in the event of an error in the service and failure to set consents, Toggle
switch will return to its previous, correct state. By modifying the isGdprAccepted
flag in the changePermissionState()
method, we can easily test its current operation. Optionally, in case .failure
it is possible to display an error alert about unsuccessful change of consents or modify the deadline value to increase the interval between switch state change animations.
Final result
Summary
The above solution is not perfect, everyone looks to the future with great hope, waiting for further updates. However, at the moment, it will definitely facilitate the unification and synchronization of the interface and logic layers, which translates into getting rid of future problems related to the maintenance of the application and taking care of its proper functioning.
Hope you enjoyed learning a few things about SwiftUI. Feel free to follow me on Twitter for updates on upcoming articles.