I want to modify my state inside a function but xcode gave this error:
Modifying state during view update, this will cause undefined behavior.
struct ContentView: View {
@State private var offsetEnum: OffsetEnum = .left
var body: some View {
VStack {
MyView(offsetEnum: offsetEnum)
Button("update") {
if offsetEnum == .left {
offsetEnum = .right
}
else {
offsetEnum = .left
}
}
}
.padding()
}
}
struct MyView: View {
let offsetEnum: OffsetEnum
@State private var angle: Angle = .zero
var body: some View {
Text("Hello, world!")
.rotationEffect(angle)
.offset(offsetCalculator())
}
func offsetCalculator() -> CGSize {
switch offsetEnum {
case .left:
angle -= Angle(degrees: 45.0)
return CGSize(width: -200.0, height: .zero)
case .right:
angle += Angle(degrees: 45.0)
return CGSize(width: 200.0, height: .zero)
}
}
}
enum OffsetEnum {
case left, right
}
As you can see the offset can be left or right but even if we are in same posation I want be able update the angle via pressing the button. How to solve this issue?
The problem is that the function which calculates the offset is also updating the state variable angle
. This is not allowed in a modifier such as .offset
. But it would be fine if called from an action callback.
So to fix, you could add another state variable to store the offset and update both the angle and offset whenever the enum value changes. This is done using an .onChange
callback. Like this:
struct MyView: View {
let offsetEnum: OffsetEnum
@State private var angle: Angle = .zero
@State private var offset = CGSize.zero
var body: some View {
Text("Hello, world!")
.rotationEffect(angle)
.offset(offset)
.onChange(of: offsetEnum) { newVal in
offset = offsetCalculator(direction: newVal)
}
}
func offsetCalculator(direction: OffsetEnum) -> CGSize {
switch offsetEnum {
case .left:
angle -= Angle(degrees: 45.0)
return CGSize(width: -200.0, height: .zero)
case .right:
angle += Angle(degrees: 45.0)
return CGSize(width: 200.0, height: .zero)
}
}
}