SwiftUI点击加入购物车后View自动pop回产品分类页问题排查
问题原因
你遇到的自动pop导航栈、控制台输出Unable to present. Please file a bug.报错,核心是ProductsView的sheet布局错误导致SwiftUI导航状态混乱:
- 你把
sheet修饰符挂载到了ForEach循环的每一个商品单元格上,所有单元格共用同一个@State var showDetailView布尔状态变量 - 当你点击加入购物车时,会修改
ProductViewModel里@Published修饰的selectedProducts数组,触发整个ProductsView重绘 - 重绘时多个共用同一状态的
sheet会让SwiftUI无法正确管理页面层级,直接触发导航栈回退,出现自动返回产品分类页的问题
修复方案
- 移除
ForEach内部每个单元格绑定的sheet修饰符,删除无用的@State var showDetailView变量 - 在
ProductsView的根视图上使用sheet(item:)方法绑定selectedProduct来唤起商品详情页,避免状态冲突
修改后的ProductsView核心代码示例:
struct ProductsView : View { @EnvironmentObject var prodViewModel : ProductViewModel var columns = Array(repeating:GridItem(.flexible()) , count: 2) @AppStorage("user_id") var userId = "" @Binding var catID : String @State var store : Store @State private var showToast = false @State var showCartView : Bool = false var body: some View{ ScrollView{ LazyVGrid(columns: columns, spacing:30){ let withIndex = prodViewModel.productArray.enumerated().map({ $0 }) ForEach(withIndex, id: \.element.id){ index, product in ProductGridView(prodViewModel: _prodViewModel, showToast: $showToast, product: product,store: store) .onTapGesture { prodViewModel.ClickedProduct(product: product) } } } // 原有导航栏配置保持不变 .padding(.leading, 15) .padding(.trailing, 15) .navigationBarItems(trailing: Button(action: { self.showCartView.toggle() }) { Image(systemName: "cart.fill").imageScale(.large).font(.title3) } .overlay(Badge(count: prodViewModel.getSelectedProduct().count)) ) } // 移到外层的sheet,用item绑定自动管理状态 .sheet(item: $prodViewModel.selectedProduct) { product in ProductDetailsView(store: store, showDetailView: .constant(false)) // 建议ProductDetailsView内部使用@Environment(\.dismiss)来关闭页面,不需要外部传Binding } // 原有toast、NavigationLink、onAppear配置保持不变 .toast(isShowing: $showToast, msg: "Added to cart", img: "cart") .background( NavigationLink( destination: CartView(prodViewModel: _prodViewModel, store: store, selectedCatID: catID), isActive: $showCartView, label: { } ) ) .onAppear{ prodViewModel.FetchProductByCategory(storeID: store.id ?? "", catID: catID) } } }
- 可选优化:如果你的项目适配iOS 16+,可以将购物车的
NavigationLink替换成navigationDestination修饰符,进一步降低导航状态冲突的概率。
内容的提问来源于stack exchange,提问作者Mac_Play
相关产品推荐
相关产品推荐

