使用 ForEach + Stepper SwiftUI 增加多个结构变量
Increment Multiple Struct Variables using ForEach + Stepper SwiftUI
我有一份披萨配料清单。列表中的每一项都是一个结构:
struct Topping: Identifiable {
let name: String
let price: Double
@State var amount: Int
let id = UUID()
}
列表在文件 MenuDataService.swift 中的 Class 中创建,使用静态 let 定义,然后在 ViewModel 文件中初始化:
//FILE MenuDataService.swift
Class MenuDataService {
static let toppingsList: [Topping] = [Topping(name: "Cheese", price: 3.00, amount: 0), Topping(name: "Sauce", price: 3.00, amount: 0)]
}
//FILE MenuViewModel.swift
Class MenuViewModel: ObservableObject {
@Published var toppingsList: [Topping]
init() {
toppingsList = MenuDataService.toppingsList
self.toppingsList = toppingsList
}
}
在视图中,我正在视图中使用 .environmentobject 访问 object。我正在使用 ForEach 循环遍历浇头列表,显示浇头的名称和数量,然后是应该递增或递减 'amount' 变量的步进器。
@EnvironmentObject private var vm = MenuViewModel
let toppingsList: [Topping]
var body: some View {
VStack {
ForEach(toppingsList, id: \.id) { topping in
Stepper("\(topping.name): \(topping.amount)", value: topping.$amount)
}
}
}
struct ExtraToppingsView_Previews: PreviewProvider {
static var previews: some View {
ExtraToppingsView(toppingsList: MenuViewModel.init().toppingsList)
.environmentObject(MenuViewModel())
}
}
我在 Stepper() 代码行中遇到此错误:在安装到视图之外访问状态的值。这样会导致初始值的Binding常量,不会更新。
单击 'Cheese' 步进器中的“+”时,它应该递增变量,并将标题更改为 'Cheese: 1',但标题保持不变。我假设这与“@State var amount”变量有关,或者与步进器中的“$amount”变量有些绑定。如果有人能指出我正确的方向,将不胜感激。
您的大部分代码都很接近——只是需要细微的差别才能使其正常工作。查看我的更改的内联评论:
struct Topping: Identifiable {
let id = UUID()
let name: String
let price: Double
var amount: Int //don't include `@State` in non-Views
}
//no changes
class MenuDataService {
static let toppingsList: [Topping] = [Topping(name: "Cheese", price: 3.00, amount: 0), Topping(name: "Sauce", price: 3.00, amount: 0)]
}
class MenuViewModel: ObservableObject {
@Published var toppingsList: [Topping]
init() {
toppingsList = MenuDataService.toppingsList
//remove unnecessary duplicate assignment
}
}
//This is the parent view -- may be called something different in your code
struct ContentView : View {
@StateObject private var vm = MenuViewModel() //declare as @StateObject
var body: some View {
ExtraToppingsView()
.environmentObject(vm) //pass the environment object
}
}
struct ExtraToppingsView : View {
@EnvironmentObject private var vm : MenuViewModel //no need to take the toppingsList parameter separately -- just use the environment object
var body: some View {
VStack {
ForEach($vm.toppingsList) { $topping in //use element binding to get a mutable binding to each item
Stepper("\(topping.name): \(topping.amount)", value: $topping.amount) //see change of the position of the $ character
}
}
}
}
struct ExtraToppingsView_Previews: PreviewProvider {
static var previews: some View {
ExtraToppingsView()
.environmentObject(MenuViewModel())
}
}
有关元素绑定的更多信息:https://www.swiftbysundell.com/articles/bindable-swiftui-list-elements/
我有一份披萨配料清单。列表中的每一项都是一个结构:
struct Topping: Identifiable {
let name: String
let price: Double
@State var amount: Int
let id = UUID()
}
列表在文件 MenuDataService.swift 中的 Class 中创建,使用静态 let 定义,然后在 ViewModel 文件中初始化:
//FILE MenuDataService.swift
Class MenuDataService {
static let toppingsList: [Topping] = [Topping(name: "Cheese", price: 3.00, amount: 0), Topping(name: "Sauce", price: 3.00, amount: 0)]
}
//FILE MenuViewModel.swift
Class MenuViewModel: ObservableObject {
@Published var toppingsList: [Topping]
init() {
toppingsList = MenuDataService.toppingsList
self.toppingsList = toppingsList
}
}
在视图中,我正在视图中使用 .environmentobject 访问 object。我正在使用 ForEach 循环遍历浇头列表,显示浇头的名称和数量,然后是应该递增或递减 'amount' 变量的步进器。
@EnvironmentObject private var vm = MenuViewModel
let toppingsList: [Topping]
var body: some View {
VStack {
ForEach(toppingsList, id: \.id) { topping in
Stepper("\(topping.name): \(topping.amount)", value: topping.$amount)
}
}
}
struct ExtraToppingsView_Previews: PreviewProvider {
static var previews: some View {
ExtraToppingsView(toppingsList: MenuViewModel.init().toppingsList)
.environmentObject(MenuViewModel())
}
}
我在 Stepper() 代码行中遇到此错误:在安装到视图之外访问状态的值。这样会导致初始值的Binding常量,不会更新。
单击 'Cheese' 步进器中的“+”时,它应该递增变量,并将标题更改为 'Cheese: 1',但标题保持不变。我假设这与“@State var amount”变量有关,或者与步进器中的“$amount”变量有些绑定。如果有人能指出我正确的方向,将不胜感激。
您的大部分代码都很接近——只是需要细微的差别才能使其正常工作。查看我的更改的内联评论:
struct Topping: Identifiable {
let id = UUID()
let name: String
let price: Double
var amount: Int //don't include `@State` in non-Views
}
//no changes
class MenuDataService {
static let toppingsList: [Topping] = [Topping(name: "Cheese", price: 3.00, amount: 0), Topping(name: "Sauce", price: 3.00, amount: 0)]
}
class MenuViewModel: ObservableObject {
@Published var toppingsList: [Topping]
init() {
toppingsList = MenuDataService.toppingsList
//remove unnecessary duplicate assignment
}
}
//This is the parent view -- may be called something different in your code
struct ContentView : View {
@StateObject private var vm = MenuViewModel() //declare as @StateObject
var body: some View {
ExtraToppingsView()
.environmentObject(vm) //pass the environment object
}
}
struct ExtraToppingsView : View {
@EnvironmentObject private var vm : MenuViewModel //no need to take the toppingsList parameter separately -- just use the environment object
var body: some View {
VStack {
ForEach($vm.toppingsList) { $topping in //use element binding to get a mutable binding to each item
Stepper("\(topping.name): \(topping.amount)", value: $topping.amount) //see change of the position of the $ character
}
}
}
}
struct ExtraToppingsView_Previews: PreviewProvider {
static var previews: some View {
ExtraToppingsView()
.environmentObject(MenuViewModel())
}
}
有关元素绑定的更多信息:https://www.swiftbysundell.com/articles/bindable-swiftui-list-elements/