简体   繁体   中英

How do I set my environment object to user input in SwiftUI?

I am currently using tab views to navigate between 4 views in my project, and the initial view is my profileView, where I want the user to input their information and goals, such as age, height etc. **However I am really struggling to find good examples and instructions on how to get user input and set my environment object to that user input. I was thinking of just using forms, but it seems unnecessary and im not too sure how to change the environment object to what the user has set. Does anyone have any good documentation they can refer me to, or show me an example of how to get user input and set my environment object to that data. (I am also not sure if this is necessary, as I will also later be storing it in userdefaults or coredata.

This is my model class which is my class data for the user. Ignore the set values at the bottom for now, they will all be set to empty when the project is in later development.

class UserInfoModel: ObservableObject {
    
    
    struct UserInfo: Identifiable {
        var id = UUID()
        var firstName: String
        var lastName: String
        var height: Int
        var weight: Int
        var gender: String
        var age: Int
        
    }
    
    struct DailyCalorieGoals: Identifiable{
        var id = UUID()
        var calorieGoal: Int
        var fatGoal: Int
        var proteinGoal: Int
        var carbGoal: Int

    }
    
    struct CurrentCalorieProgress: Identifiable{
        var id = UUID()
        var calorieProgress: Int
        var fatProgress: Int
        var carbProgress: Int
    }
    
    @Published var personUserInfo = UserInfo.init(firstName: "", lastName:"", height: 0, weight: 0, gender: "", age: 0)
    @Published var personDailyCalorieGoals = DailyCalorieGoals.init(calorieGoal: 2400, fatGoal: 0, proteinGoal: 0, carbGoal: 0)
    @Published var personCurrentCalorieProgress = CurrentCalorieProgress.init(calorieProgress: 0, fatProgress: 0, carbProgress: 0)
    
   
}

So when I am in my profile view how do i get the user input and set my environment object to that data?

The above has been solved, thanks to the help provides so far, however using the method linked below I get the following, but I am not sure how to change the value of my double environment object to the fatInputString:

New code to get input from user

Text("Fat: \(self.person.personDailyCalorieGoals.fatGoal, specifier: "%.0f")g")
                            }
                            TextField("Enter new fat goal (g)", text: $fatInputString ).keyboardType(.numberPad)
                                .onReceive(Just(fatInputString)) { newValue in
                                                let filtered = newValue.filter { "0123456789".contains($0) }
                                                if filtered != newValue {
                                                    self.fatInputString = filtered
                                                }

But how do i set my environment object

self.person.personDailyCalorieGoals.fatGoal 

equal to

self.inputString 

from the above code }

Using a Form isn't required -- it just makes the formatting of your user input elements a little more standardized on iOS/macOS.

Regardless of whether you use Form or not, you'll be using various user input elements and assigning them Bindings on your UserInfoModel . SwiftUI/Combine makes this really easy to do with the $ operator.

Here's an example of how to get input to a couple of your fields. You can see that when the field info changes, the value is reflected in the EnvironmentObject which ContentView owns -- it displays the value at the top above the EditorView

struct ContentView : View {
    @ObservedObject var userInfo = UserInfoModel()
    
    var body: some View {
        VStack {
            Text("Name: \(userInfo.personUserInfo.firstName)")
            Text("Weight: \(userInfo.personUserInfo.weight)")
            Text("Carb: \(userInfo.personCurrentCalorieProgress.carbProgress)")
            EditorView().environmentObject(userInfo)
        }
    }
}

struct EditorView : View {
    @EnvironmentObject private var userInfo : UserInfoModel
    
    var body: some View {
        Form {
            TextField("First name", text: $userInfo.personUserInfo.firstName)
            Stepper("Weight", value: $userInfo.personUserInfo.weight, in: 0...500)
            Stepper("Carb progress", value: $userInfo.personCurrentCalorieProgress.carbProgress, in: 0...1000, step: 10)
        }
    }
}

Update based on comments : Edit to show your request about numerical text input:

struct EditorView : View {
    @EnvironmentObject private var userInfo : UserInfoModel
    @State var fatInputString = "" //<-- Here
    
    var body: some View {
        Form {
            TextField("First name", text: $userInfo.personUserInfo.firstName)
            Stepper("Weight", value: $userInfo.personUserInfo.weight, in: 0...500)
            Stepper("Carb progress", value: $userInfo.personCurrentCalorieProgress.carbProgress, in: 0...1000, step: 10)
            Text("Fat: \(userInfo.personDailyCalorieGoals.fatGoal)g") //<-- Here
            TextField("Enter new fat goal (g)", text: $fatInputString ).keyboardType(.numberPad)
                .onReceive(Just(fatInputString)) { newValue in
                    let filtered = newValue.filter { "0123456789".contains($0) }
                    if filtered != newValue {
                        self.fatInputString = filtered
                    }
                    if let goal = Int(fatInputString), goal != userInfo.personDailyCalorieGoals.fatGoal {  //<-- Here
                        userInfo.personDailyCalorieGoals.fatGoal = goal
                    }
                }
        }
        
    }
}

Note that in your updated code you had a bug where the fat amount would always be displayed as 0. Make sure to look at each line with //<-- Here marked

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM