在我的项目中,用户可以有两个最喜欢的产品。他们可以通过点击其中一个(ProductView)来更改它们。点击一个后,将显示一个名为“ProductSheet”的视图。我尝试从上一个视图中携带id,但它不在那里。我需要将id传递到'ProductSheet'和'ProductRowView'中,以便执行更改最喜欢的产品的功能。
我不明白为什么product_id在'ProductSheet'和'ProductRowView'视图中没有值。下面是代码的简化版本:
struct FavouriteProducts: View {
@StateObject var favouriteProductsModel = FavouriteProductsViewModel()
@State private var showingSheet = false
@State var selectedProduct: String?
@State var product_id: String?
var body: some View {
ZStack {
let defaults = UserDefaults.standard
let keyString: String? = defaults.string(forKey: "key") ?? ""
VStack {
HStack {
Text("Tap to change favourite product")
}
HStack(spacing: 25) {
ForEach(favouriteProductsModel.favourite_products, id: \.id){ product in
VStack {
Image("ProductImage")
.resizable()
Text(String(product.product_name ?? ""))
}
.onTapGesture {
selectedProduct = product.id
self.product_id = product.id ?? ""
self.showingSheet = true
//selectedProduct does have a value in this print statement
print("Tapped Product ID: \(String(describing: selectedProduct))")
}
.sheet(item: $selectedProduct) {
favouriteProductsModel.fetchFavouriteProducts(key: keyString ?? "")
} content: { item in
ProductSheet(product_id: selectedProduct ?? "")
}
}
}
}
}
.onLoad {
let defaults = UserDefaults.standard
let keyString: String? = defaults.string(forKey: "key") ?? ""
self.favouriteProductsModel.fetchFavouriteProducts(key: keyString ?? "")
}
}
}
struct ProductSheet: View {
@StateObject var marketplaceModel = MarketplaceViewModel()
@State var product_id: String?
var body: some View {
VStack {
// The product_id here is not being displayed, because the variable has no value
Text(product_id ?? "")
ForEach(marketplaceModel.filteredProduct, id:\.self){ product in
ProductRowView(productData: product, product_id: product_id ?? "")
}
}
}
}
struct ProductRowView: View {
@Environment(\.dismiss) var dismiss
@StateObject var favouriteProductsModel = FavouriteProductsViewModel()
@State private var isShowingDetailView = false
@State var selectedProduct : ProductTile?
@State var new_id = ""
var productData: ProductRow
var product_id: String
var body: some View {
VStack {
HStack {
Text(productData.title)
HStack {
NavigationLink("", isActive: $isShowingDetailView) {
ProductSeeAllView(productData: productData, product_id: productData.id)
}.navigationTitle("")
Button("See All") {
isShowingDetailView = true
}
Image(systemName: "chevron.right")
}
}
HStack {
ScrollView {
HStack {
ForEach(productData.products ?? []) { product in
ProductView(productData: product)
.onTapGesture {
new_id = product.id ?? ""
selectedProduct = product
print("Product id: \(selectedProduct?.id ?? "")")
let defaults = UserDefaults.standard
let keyString: String? = defaults.string(forKey: "key") ?? ""
favouriteProductsModel.changeFavouriteProducts(key: keyString ?? "", current_id: product_id, new_id: new_id ) { (success) in
if success {
dismiss()
} else {
print("Unsuccessful...")
}
}
}
}
}
}
}
}
}
}
当初始化'ProductSheet'和'ProductRowView'时,我应该传递product_id,但它不起作用。为什么会这样?
编辑:通过进一步的测试,如果第二次初始化工作表,似乎会通过id。它似乎从来没有工作第一次。
3条答案
按热度按时间ds97pgxw1#
我简化了您的代码以向您展示一个可行的解决方案。
工作表是在视图初始化时创建的,因此ProductSheet初始化为nil乘积。您必须添加
@Binding
以获得所需的行为。fcwjkofz2#
应该是
let
而不是@State var
。对于let
,body
将被自动调用,然后传入的值从上次这个View结构体初始化时起发生了变化,例如。g的。仅供参考,我们不需要SwiftUI中的视图模型对象,因为这是View结构的工作。
@StateObject
用于当您需要在@State
中存储引用类型时,例如。例如,当执行异步操作时。如果你使用@StateObject
来实现视图模型,你会遇到SwiftUI为视图数据设计的不可变View
结构体所要消除的那种一致性错误。yc0p9oo03#
问题是,数据在第一次初始化时没有传递到工作表。下面的代码阻止了这个bug: