繁体   English   中英

如何将我的环境 object 设置为 SwiftUI 中的用户输入?

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

我目前正在使用选项卡视图在项目中的 4 个视图之间导航,初始视图是我的 profileView,我希望用户在其中输入他们的信息和目标,例如年龄、身高等。**但是我真的很难找到有关如何获取用户输入并将我的环境 object 设置为该用户输入的良好示例和说明。 我正在考虑只使用 forms,但这似乎没有必要,而且我不太确定如何将环境 object 更改为用户设置的环境。 有没有人可以参考我的任何好的文档,或者向我展示如何获取用户输入并将我的环境 object 设置为该数据的示例。 (我也不确定这是否有必要,因为我稍后也会将它存储在 userdefaults 或 coredata 中。

这是我的 model class 这是我为用户提供的 class 数据。 暂时忽略底部的设置值,项目后期开发时全部设置为空。

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)
    
   
}

那么当我在我的个人资料视图中时,我如何获取用户输入并将我的环境 object 设置为该数据?

由于到目前为止提供的帮助,上述问题已经解决,但是使用下面链接的方法我得到以下内容,但我不确定如何将我的双环境 object 的值更改为 fatInputString:

获取用户输入的新代码

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
                                                }

但是我如何设置我的环境 object

self.person.personDailyCalorieGoals.fatGoal 

等于

self.inputString 

从上面的代码}

不需要使用Form ——它只是让用户输入元素的格式在 iOS/macOS 上更加标准化。

无论您是否使用Form ,您都将使用各种用户输入元素并在您的UserInfoModel上为它们分配绑定。 SwiftUI/Combine 使用$运算符使这非常容易。

这是一个如何获取几个字段输入的示例。 可以看到,当字段信息发生变化时,值会反映在ContentView拥有的EnvironmentObject中——它显示在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)
        }
    }
}

根据评论更新:编辑以显示您对数字文本输入的请求:

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
                    }
                }
        }
        
    }
}

请注意,在您更新的代码中,您有一个错误,即脂肪量始终显示为 0。确保查看每一行带有//<-- Here标记

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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