When a SwiftUI view has a complex logic, i like to employ an enum to represent it’s state (often in a viewmodel/service).
struct FooView {
enum ProgressState {
case idle
case loading
case completed(Model)
case error
var stateName: String { ... }
}
@State var state: ProgressState = .idle
...
PROBLEM:
What i’d like tho, is a way or methodology to connect bindables to a specific enum case. In this example, to show an alert (or a sheet), since something like <<$state.error>>
is obviously not possible.
...
var body: some View {
Text(state.stateName)
// show alert on error
.alert("oops there was an error",
isPresented: <<$state.error>>)
{ //1.
...
}
}
}
CURRENT ALTERNATIVE
The easiest solution is to use additional variables, but i really do not like to keep them synchronised manually.
BETTER SOLUTIONS?
I was exploring using combine to update the additional variable upon state
var changes, the problem is always that the bindable needs to change it’s state as well, but in this case the alert, does not know to which state to bring it back to.
So maybe a protocol for the enum and an extension to alert and sheet to handle these instead of Bindable ? Has anybody tried a similar approach or know a better one?
Thank you
3
Answers
Method 1 – Without helpers variavles
You can bind it directly to the
error
state like:⚠️ note that the default
OK
button will not change the state in this methodMethod 2 – With a
Binding<Bool>
variable in betweenAnother way is that you can wire-up the state to the binding:
💡 Note that there is no need to manually tell the view what to do like what we do in the
UIKit
, but you must declare what the state would be in every situation.For this case, it is obvious that you need to see the alert on the
error
state, but it’s not clear the other way. So you should filter it down to just 2 states (abool
) anyway.You just need to use a computed binding like :
SwiftUI provides a solution to present
LocalizedError
You can create a simple
enum
that can present any standardError
or custom errors.Then you can modify your progress enum.
You can then trigger an
alert
(or sheet) when that state is triggeredHere is the full code.
This provides an independent
alert
variable so the presentation of the.alert
does not conflict with theView
behind it or make any unsafe assumptions.