New to SwiftUI.

I want to change the string calBudget in the UserSettings view and convert it to Int in the ContentView. the first problem is the Integer conversion is not working with my code. The second problem is, every keystroke in the UserSettings view is generating a new UserSettings view creating a bunch of nested views.

struct ContentView: View {

    @AppStorage("calBudget") var calBudget = "1700"
    @AppStorage("calsBudget") var calsBudget = 0

    var body: some View {
        NavigationView {
            Form {
                Text("Budget: \(self.calBudget)")
                Text("to integer \(String(self.calsBudget))")
            }.toolbar {
                ToolbarItem() {
                    NavigationLink( destination: UserSettings(calBudget: $calBudget, calsBudget: $calsBudget)) { Text("settings") }
                }
            }
        }
    }
}

struct UserSettings: View {
    @Binding var calBudget: String
    @Binding var calsBudget: Int
    var body: some View {
        Form {
            HStack {
                TextField("Budget: ", text: self.$calBudget)
                Button(action: {
                    let calsBudget: Int = Int(self.calBudget ) ?? 1000
                }) { Text("make into integer")}
            
            }
        }
    
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
    
        ContentView( )
    }
}
1

There are 1 best solutions below

2
On BEST ANSWER

the first problem is the Integer conversion is not working with my code

This is your code currently:

let calsBudget: Int = Int(self.calBudget ) ?? 1000

Here, you're creating a new constant, calsBudget. Then you do nothing with it, throwing it away. Instead, you want to modify the existing @Binding var calsBudget: Int, so assign the value.

calsBudget = Int(self.calBudget ) ?? 1000

The second problem is, every keystroke in the UserSettings view is generating a new UserSettings view creating a bunch of nested views

This happens because of this code:

.toolbar {
    ToolbarItem() {
        NavigationLink( destination: UserSettings(calBudget: $calBudget, calsBudget: $calsBudget)) { Text("settings") }
    }
}

NavigationLink must always be inside a NavigationView. Whenever you put it outside, for example in a toolbar, you'll run into weird issues.

Here's the fixed code:

struct ContentView: View {

    @AppStorage("calBudget") var calBudget = "1700"
    @AppStorage("calsBudget") var calsBudget = 0
    @State var settingsPresented = false

    var body: some View {
        NavigationView {
            
            /// NavigationView must only contain 1 view, so wrap Form and NavigationLink inside VStack
            VStack {
                Form {
                    Text("Budget: \(self.calBudget)")
                    Text("to integer \(String(self.calsBudget))")
                }
                
                /// NavigationLink must be inside NavigationView
                NavigationLink(
                    destination: UserSettings(calBudget: $calBudget, calsBudget: $calsBudget),
                    isActive: $settingsPresented) /// activates when `settingsPresented` is true
                    { EmptyView() }
            }
            .toolbar {
                ToolbarItem() {
                    Button("settings") {
                        settingsPresented = true /// activate the NavigationLink
                    }
                }
            }
        }
    }
}

struct UserSettings: View {
    @Binding var calBudget: String
    @Binding var calsBudget: Int
    var body: some View {
        Form {
            HStack {
                TextField("Budget: ", text: self.$calBudget)
                
                Button(action: {
                    calsBudget = Int(self.calBudget ) ?? 1000 /// assign value, not create
                }) { Text("make into integer")}
            
            }
        }
    }
}