如何在 SwiftUI 中将我的环境对象设置为用户输入?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中将我的环境对象设置为用户输入?【英文标题】:How do I set my environment object to user input in SwiftUI? 【发布时间】:2021-02-16 11:36:01 【问题描述】:我目前正在使用选项卡视图在我的项目中的 4 个视图之间导航,初始视图是我的 profileView,我希望用户在其中输入他们的信息和目标,例如年龄、身高等。**然而我是真的很难找到关于如何获取 用户输入 并将我的环境对象设置为该用户输入的良好示例和说明。我想只使用表单,但这似乎没有必要,而且我不太确定如何将环境对象更改为用户设置的对象。有没有人有任何好的文档可以参考我,或者向我展示如何获取用户输入并将我的环境对象设置为该数据的示例。 (我也不确定这是否有必要,因为我稍后也会将其存储在 userdefaults 或 coredata 中。
这是我的模型类,它是我的用户类数据。底部的设置值暂时忽略,项目后期开发时全部设置为空。
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)
那么当我在我的个人资料视图中时,我如何获取用户输入并将我的环境对象设置为该数据?
由于到目前为止提供的帮助,上述问题已经解决,但是使用下面链接的方法我得到以下内容,但我不确定如何将我的双环境对象的值更改为 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
但是我如何设置我的环境对象
self.person.personDailyCalorieGoals.fatGoal
等于
self.inputString
从上面的代码
【问题讨论】:
见Apple SwiftUI tutorial Handling User Input 【参考方案1】:使用 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)
基于 cmets 的更新: 编辑以显示您对数字文本输入的要求:
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
标记的每一行
【讨论】:
这是一个非常棒的答案,非常感谢!但是,我还有最后一个问题。如何让用户使用编辑文本或类似的东西来调整 int 值 $userInfo.personUserInfo.weight?谢谢! 在 TextField 中接受 Int 有一些非常好的答案(这需要一些摆弄):***.com/questions/58733003/… 如果您需要针对您的具体情况进行澄清,请告诉我。 好的,所以我能够获取用户的输入,但是在使用以下内容时出现以下错误: let fatInput = String(self.person.personDailyCaloriGoals.fatGoal) 然后尝试set TextField("Enter Fat", text: fatInput ) 您实际上并没有记下错误,但我假设它告诉您必须使用绑定,而不仅仅是 TextField 中的字符串。查看我链接到的答案以及它如何为此使用 @State 变量,并查看它使用的$
运算符。如果需要,您可以编辑此问题以显示您的代码,以便我提供更具体的建议。
刚刚编辑了我的答案,保留原始内容以防其他人需要它,非常感谢您迄今为止的帮助!以上是关于如何在 SwiftUI 中将我的环境对象设置为用户输入?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中将 Firebase 结果转换为 List
在 SwiftUI 中将 swift 应用程序上的所有 Text() 设置为相同的颜色