Reputation: 382
I'm trying to get progress value of a progress bar based on another value. Both of these variables (waterQuantity and progress) are in property wrappers @State
This is my code :
struct CircularProgressBar: View {
@State var waterQuantity: Int
@State var progress: Float = (1 + (Float(waterQuantity)/Float(1500))) * 100
var body: some View {
ZStack {
Circle()
.foregroundColor(.white)
.padding(25)
.overlay(
Circle()
.trim(from: 0.0, to: CGFloat(min(self.progress, 1.0)))
.stroke(style: StrokeStyle(lineWidth: 25
, lineCap: .round, lineJoin: .round))
.foregroundColor(Color.blue)
.rotationEffect(Angle(degrees: 270.0))
.animation(.linear)
.padding(50)
)
VStack {
Text(String(format: "%.0i mL", 500))
.font(.largeTitle)
.bold()
.foregroundColor(Color("bgStart"))
Text("1500 mL")
.foregroundColor(.gray)
}
}
}
As you can see, I cannot initialise progress with another variable that has not been initialized yet. I tried passing values with init() and mutating func, but none of these solutions worked for me 😕
Upvotes: 3
Views: 1649
Reputation: 225
Since progress is dependent on the waterQuantity passed into the view, I would suggest performing this computation within the init function. And then initialing progress with a new initial state value.
@State private var waterQuantity: Int
@State private var progress: Float = 0.0
init(waterQuantity: Int){
self._waterQuantity = State(initialValue: waterQuantity)
self._progress = State(initialValue: (1 + (Float(waterQuantity)/Float(1500))) * 100)
}
But since it doesn't look like your using waterQuantity within the body of the View. Then it probably doesn't need to have a @State annotation wrapper, and the code could look something like this instead:
private var waterQuantity: Int
@State private var progress: Float = 0.0
init(waterQuantity: Int){
self.waterQuantity = waterQuantity
self._progress = State(initialValue: (1 + (Float(waterQuantity)/Float(1500))) * 100)
}
Upvotes: 0
Reputation: 100541
You may not need to make this
@State var progress: Float = Float(waterQuantity)/Float(1500)
a property just leave only waterQuantity
and copy paste that code inside the body of view and it'll be refreshed when waterQuantity
is changed
Upvotes: 1
Reputation: 203
You should change progress to a computed property that doesn't store any value, but rather calculates it's value dynamically based on the value of waterQuantity:
var progress: Float {
Float(waterQuantity)/Float(1500)
}
Now when waterQuantity is being updated, your view will still be redrawn because waterQuantity is used inside this computed property, which is in turn being used in your view.
Upvotes: 5