1

I am working on a shopping app with firestore as a backend, where users add products to the cart.(Shop -> Product Category -> Product -> Add to cart). There is some weird behavior when the user clicks on the add to cart button. For the first time when the user clicks on Add to cart, the view automatically pops back to the Product category screen. Then if I click on any product category it goes to the product screen and pops back automatically. I am stuck with this issue for a couple of days, Please shed some light on what I am doing wrong. Thanks a ton.

Product

struct Product : Identifiable, Codable {
@DocumentID var id : String?
var name : String?
var price : String?
var available : Bool = false
var quantity : Int = 1
var category : String?

enum CodingKeys: String, CodingKey {
    case id, name, price, category, available
}
}

ProductViewModel

public class ProductViewModel: ObservableObject {
@Published var productArray : [Product] = []
@Published var selectedProducts : [Product] = []
@Published var productTotal = ProductTotal(totalAmt: 0)
@Published var productImgDict : [String : String] = [:]
@Published var selectedProduct = Product()

var products : [Product] = []
var dummyProductLst : [Product] = []
var dummyCartItems : [Product] = []
var firestore = Firestore.firestore()
var storageRef = Storage.storage()
init(){
}

func ClickedProduct(product : Product) {
    // Single product selection
    selectedProduct = product
}

func getClickedProduct() -> Product{
    return selectedProduct
}

func setSelectedProduct(product : Product)  {
        selectedProducts.append(product)
        self.dummyCartItems.append(product)
        self.setDefaultProductQty(product: product)
}


func setDefaultProductQty(product : Product)  {
    for index in self.selectedProducts.indices {
        if product.id == self.selectedProducts[index].id {
            //By default setting the quantity to 1 when adding a product
            self.selectedProducts[index].quantity =  +1
        }else{
            print("not matched")
        }
    }
}

func getSelectedProduct() -> [Product] {
    return self.selectedProducts
}

func deleteProduct(index : IndexSet)  {
    self.selectedProducts.remove(atOffsets: index)
    self.dummyCartItems.remove(atOffsets: index)
}

func getTotalAmount() -> ProductTotal {
    var totalAmt = 0;
    for item in self.selectedProducts {
        totalAmt = totalAmt + Int(item.price?.floatValue ?? 0)
    }
    return ProductTotal( totalAmt: totalAmt)
}

func setQuantity(index : Int, qty : Int = 1)  {
    self.selectedProducts[index].quantity = qty
}

func setgetUpdatedPrice(index : Int, qty : Int, itemID : String = "")  -> String {
    var calculatedAmt = 0
    if let data = self.dummyCartItems.first(where: {$0.id == itemID}) {
        calculatedAmt = Int(data.price?.floatValue ?? 0) * qty
        self.selectedProducts[index].price = String(calculatedAmt)
    } else {
        // item could not be found
    }
    _ = getTotalAmount()
    print(calculatedAmt)
    return String(calculatedAmt)
}


}

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

//    @State var selectedProds : Product
@State var showDetailView: 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 {
                    showDetailView.toggle()
                    prodViewModel.ClickedProduct(product: product)
                }.sheet(isPresented: $showDetailView) {
                    ProductDetailsView(store: store, showDetailView: $showDetailView)
                }

            }
        }
        .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))
        )
    }
    .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)
    }

}
}

ProductGridView

struct ProductGridView: View {
@EnvironmentObject var prodViewModel : ProductViewModel
@EnvironmentObject var partialSheetManager : PartialSheetManager
@Binding  var showToast : Bool

var product : Product
var store : Store
var body: some View {
    ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)){
        VStack(alignment: .center, spacing: 10){

            let imgURL = prodViewModel.productImgDict[product.id ?? ""]
            AnimatedImage(url: URL(string: imgURL ?? "")).resizable().frame(width: 110, height: 110).padding()

            HStack{
                Text("₹\(product.price ?? "")")
                    .foregroundColor(Color.theme.appColor)
                    .font(.title2).bold()

                Spacer(minLength: 20)

                if product.available {
                    Button(action: {
                        if self.prodViewModel.getSelectedProduct().contains(where: {  $0.id == product .id}){
                            //item found
                        }else{
                            // not found in cart - add product to array

                            if store.id == AppSettings.shared.getStoreID(){
                                prodViewModel.setSelectedProduct(product: product)
                                showToast = true
                            }else{
                                print("shop is different, you cannot add it")
                                self.partialSheetManager.showPartialSheet {
                                    ChangeShopView(store: store, product: product)
                                }
                            }

                        }
                    }, label: {
                        Image.init(systemName: "cart.badge.plus")
                            .renderingMode(Image.TemplateRenderingMode?.init(Image.TemplateRenderingMode.original))
                            .resizable()
                            .frame(width: 32, height: 30)
                    }
                    )
                }else{

                }


            }
            HStack{
                Text(product.name ?? "")
                    .font(.title3)
                    .multilineTextAlignment(.leading)
                    .foregroundColor(Color.theme.textColor)
                Spacer()
            }


        } .overlay(

            Text( product.available ? "" : "NOT AVAILABLE")
                .foregroundColor(.white)
                .background(Color.red)
                .font(.caption)
                .clipShape(RoundedRectangle(cornerRadius: 4))
                .padding(.horizontal)
            ,alignment: .center)
        .padding(.horizontal, 8)
        .frame(width :  UIScreen.main.bounds.size.width/2.4)
        .background(Color.theme.cardColor)
        .cornerRadius( 6)
        .shadow(color: Color.black.opacity(0.2), radius:5, x:-5, y:5)

    }
}
}

On clicking Add to cart button I am calling the setSelectedProduct method from ProductViewModel. ProductViewModel is an environmentObject. In the console, am getting - Unable to present. Please file a bug.

Mac_Play
  • 302
  • 4
  • 21
  • hey! do you still have this issue or you sorted it out? – Marcela Ceneviva Auslenter Apr 08 '22 at 10:03
  • Still, in iOS 14 devices, it's happening but not for all. Are you facing the same issue? – Mac_Play Apr 08 '22 at 21:17
  • Yeah, I had this issue happening in a couple of views and different things fixed it. So one of the issues was related to having multiple navigation links in the same view. For some weird reason, if you have 1, 3, 4, 5 navigation links it's fine, but if you have 2, it pops back. What fixed for me was adding an "Empty" navigation link. NavigationLink(destination: EmptyView()) { EmptyView() } The other pop back was happening because of what I describe in here https://stackoverflow.com/questions/71795291/swiftui-view-popping-back-after-button-click Let me know if any of this help. – Marcela Ceneviva Auslenter Apr 09 '22 at 12:04
  • also, try to add .navigationViewStyle(.stack) to your navigation view if you haven't already. – Marcela Ceneviva Auslenter Apr 09 '22 at 12:07

0 Answers0