Xcode 14.1 (14B47b), Ventura 13.0.1, Swift 5
When clicking the button, it prints consecutive numbers in the debug window, but the SwiftUI View does not update. I couldn't get it to work on a much more complicated app and ran into this problem. Then I reduced it to this test project, and it still dosn't work.
This should be a trivial use of @State. This is for a SwiftUI app running on MacOS.
What am I doing wrong (other than losing my mind)?
import SwiftUI
var globalCounter:Int = 0
@main
struct State_TestApp: App {
init() {
globalCounter = 1
}
var body: some Scene {
WindowGroup {
ContentView(counter:globalCounter)
}
}
}
func addOne() {
globalCounter = 1
print(globalCounter)
}
struct ContentView: View {
@State var counter:Int
var body: some View {
VStack {
Button("Add one") {
addOne()
}
Text("\(counter)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(counter:globalCounter)
}
}
CodePudding user response:
Because a global variable cannot trigger View
updates and because counter
isn't being updated, @State var counter:Int
is a source of truth that is being initialized with the value from globalCounter
there is no connection between them.
always declare state as private, and place it in the highest view in the view hierarchy that needs access to the value.
Use state as the single source of truth for a given value stored in a view hierarchy.
https://developer.apple.com/documentation/swiftui/state
CodePudding user response:
Here is the answer for those that want to do something similar.
@main
struct State_TestApp: App {
var body: some Scene {
WindowGroup {
ContentView(start:3)
}
}
}
func addOne(number:Int) -> Int {
return number 1
}
struct ContentView: View {
init(start:Int) {
counter = start
}
@State private var counter:Int
var body: some View {
VStack {
Button("Add one") {
counter = addOne(number: counter)
}
Text("\(counter)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(start:4)
}
}