英文:
User inputted TextField Array from Grid
问题
I have a grid view that has two columns, one that is static that will be populated with names, and the second that is user-inputted numbers. I have two arrays, one full of the names, and one that is initialized to 0s for all numbers. I have it displayed as:
ScrollView{
let lastRowIndex: Int = viewModel.names.count - 1
LazyVGrid(columns: columns, alignment: .center, spacing: 0){
Group {
Text("Name")
Text("Number")
}.font(.headline)
ForEach((0...lastRowIndex), id: \.self) { index in
Text(viewModel.names[index])
TextField("individual value", value: $viewModel.individualValues[index], format: .number)
}
}.padding(.horizontal)
}
This displays perfectly to start, two columns, one with every name in the array and one initialized to 0. But when I try to make any change to the number, as soon as I click off of the input it returns to 0. How do I set this up so that the numbers are saved in the individualValues array, displayed properly, and able to be used later?
Edit: My updated code is:
struct NamesAndTimes: Identifiable {
let id = UUID()
var userId: String
var fullName: String
var indivValue: Double
}
class AddTimesViewModel: ObservableObject {
var namesAndTimes: [NamesAndTimes]
...
init (users: [User]) {
self.namesAndTimes = users.map{u in
return NamesAndTimes(
userId: u.id,
fullName: u.firstName + " " + u.lastName,
indivValue: 0
)
}
}
}
struct AddTimes: View {
@ObservedObject var viewModel: AddTimesViewModel
...
ScrollView{
LazyVGrid(columns: columns, alignment: .leading, spacing: 0){
Group {
Text("Name")
Text("Number")
}.font(.headline)
ForEach($viewModel.namesAndTimes) { $rT in
Text(rT.fullName)
TextField("type",
value: $rT.indivValue,
format: .number
)
}
}.padding(.horizontal)
}
}
Which works logically, but currently does not update the view. Even when I change the value, it displays as 0. If I click back, the typed-in value displays and is entered in Firebase if I click save, but I would like the view to display.
英文:
I have a grid view that has two columns, one that is static that will be populated with names, and the second that is user inputed numbers. I have two arrays, one full of the names, and one that is initialized to 0s for all numbers. I have it displayed as:
ScrollView{
let lastRowIndex: Int = viewModel.names.count - 1
LazyVGrid(columns: columns, alignment: .center, spacing: 0){
Group {
Text("Name")
Text("Number")
}.font(.headline)
ForEach((0...lastRowIndex), id: \.self) { index in
Text(viewModel.names[index])
TextField("indiv value", value: $viewModel.individualValues[index], format: .number)
}
}.padding(.horizontal)
}
This displays perfectly to start, two columns, one with every name in the array and one initialized to 0. But when I try to make any change to the number, as soon as I click off of the input it returns to 0. How do I set this up so that the numbers are saved in the individualValues array, displayed properly, and able to be used later?
Edit: My updated code is:
struct NamesAndTimes: Identifiable {
let id = UUID()
var userId: String
var fullName: String
var indivValue: Double
}
class AddTimesViewModel: ObservableObject {
var namesAndTimes: [NamesAndTimes]
...
init (users: [User]) {
self.namesAndTimes = users.map{u in
return NamesAndTimes(
userId: u.id,
fullName: u.firstName+" "+u.lastName,
indivValue: 0
)
}
}
}
struct AddTimes: View {
@ObservedObject var viewModel: AddTimesViewModel
...
ScrollView{
LazyVGrid(columns: columns, alignment: .leading, spacing: 0){
Group {
Text("Name")
Text("Number")
}.font(.headline)
ForEach($viewModel.namesAndTimes) { $rT in
Text(rT.fullName)
TextField("type",
value: $rT.indivValue,
format: .number
)
}
}.padding(.horizontal)
}
Which works logically, but currently does not update the view. Even when I change the value, it displays as 0. If I click back the typed in value displays, and is entered in Firebase if I click save, but I would like the view to display.
答案1
得分: 1
尽管您的代码可能能够工作,前提是您使用类似于:@StateObject var viewModel = TheModel()
。
但是,最好为您的names
和individualValues
使用更强大的结构,而不是单独的数组,并通过一个共同的index
来访问它们,这不是一个好主意,也不推荐使用。
以下是我的示例代码,可以为您实现您所要求的功能:“如何设置这样的结构,使数字保存在individualValues数组中,正确显示,并能够以后使用”:
// -- 在这里,名称和值被绑定在一起
struct ModelItem: Identifiable {
let id = UUID()
var name: String
var value: Int
}
class TheModel: ObservableObject {
@Published var items: [ModelItem] = [ModelItem(name: "item-1", value: 1),
ModelItem(name: "item-2", value: 2),
ModelItem(name: "item-3", value: 3)]
}
struct ContentView: View {
@StateObject var viewModel = TheModel() // <-- 在这里
var columns: [GridItem] = [GridItem(.flexible()), GridItem(.flexible())]
var body: some View {
ScrollView{
LazyVGrid(columns: columns, alignment: .center, spacing: 0){
Group {
Text("名称")
Text("数字")
}.font(.headline)
ForEach($viewModel.items) { $item in // <-- 使用 $,而不是索引
Text(item.name)
TextField("个体值", value: $item.value, format: .number) // <-- 在这里
}
}.padding(.horizontal)
}
}
}
请注意,我已经将示例代码中的HTML实体(例如"
)替换为正常的文本,以便代码能够正确运行。
英文:
Although your code could work, given you use something like: @StateObject var viewModel = TheModel()
.
You would be better off using a more robust structure for your names
and individualValues
, than
the separate arrays, and accessing them through a common index
, not a good idea and not recommended.
Here is my example code of that approach that works for me and achieve what you ask:
How do I set this up so that the numbers are saved in the individualValues array, displayed properly, and able to be used later
// -- here, name and value are tied together
struct ModelItem: Identifiable {
let id = UUID()
var name: String
var value: Int
}
class TheModel: ObservableObject {
@Published var items: [ModelItem] = [ModelItem(name: "item-1", value: 1),
ModelItem(name: "item-2", value: 2),
ModelItem(name: "item-3", value: 3)]
}
struct ContentView: View {
@StateObject var viewModel = TheModel() // <-- here
var columns: [GridItem] = [GridItem(.flexible()), GridItem(.flexible())]
var body: some View {
ScrollView{
LazyVGrid(columns: columns, alignment: .center, spacing: 0){
Group {
Text("Name")
Text("Number")
}.font(.headline)
ForEach($viewModel.items) { $item in // <-- use $, and not index
Text(item.name)
TextField("indiv value", value: $item.value, format: .number) // <-- here
}
}.padding(.horizontal)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论