Shopping cart count disappears after changing tabs

On my shop and content views of my app, I have a shopping cart SF symbol that I've modified with a conditional to show the number of items in the cart if the number of items is above zero. However, whenever I change tabs and back again, that icon disappears even though there should be an item in the cart.

I have a video of the error, but I have no idea how to post it. Here is some of the code, let me know if you need to see more of it:

CartManager.swift

import Foundation
import SwiftUI


@Observable class CartManager {
    /*private(set)*/ var products: [Product] = []
    private(set) var total: Int = 0
    private(set) var numberofproducts: Int = 0


    
    func count() -> Int {
        numberofproducts = products.count
        return numberofproducts
    }

    func addToCart(product: Product) {
        products.append(product)
        total += product.price
        numberofproducts = products.count
    }
    
    
    func removeFromCart(product: Product) {
        products = products.filter { $0.id != product.id }
        total -= product.price
        numberofproducts = products.count
    }
    
}

ShopPage.swift

import SwiftUI

struct ShopPage: View {

    @Environment(CartManager.self) private var cartManager
    
    var columns = [GridItem(.adaptive(minimum: 135), spacing: 0)]

    
    @State private var searchText = ""
    let items = ["LazyHeadphoneBean", "ProperBean", "BabyBean", "RoyalBean", "SpringBean", "beanbunny", "CapBean"]
    
    var filteredItems: [Bean] {
        guard searchText.isEmpty else { return beans }
        return beans.filter { $0.imageName.localizedCaseInsensitiveContains(searchText) }
    }
    
    var body: some View {


        NavigationStack {
            ZStack(alignment: .top) {
                Color.white
                    .ignoresSafeArea(edges: .all)
                VStack {
                    AppBar()
                        .environment(cartManager)
                    
                    
                    ScrollView() {
                        LazyVGrid(columns: columns, spacing: 20) {
                            ForEach(productList, id: \.id) { product in
                                NavigationLink {
                                    beanDetail(product: product)
                                        .environment(cartManager)
                                } label: {
                                    ProductCardView(product: product)
                                        .environment(cartManager)
                                }
                            }
                        }
                    }
                }
.navigationBarDrawer(displayMode: .always))
            }
        }
        .environment(cartManager)
    }    
    
    var searchResults: [String] {
        if searchText.isEmpty {
            return items
        } else {
            return items.filter { $0.contains(searchText)}
        }
    }
}

#Preview {
    ShopPage()
        .environment(CartManager())
}

struct AppBar: View {
    @Environment(CartManager.self) private var cartManager

    var body: some View {
        NavigationStack {
            VStack (alignment: .leading){
                HStack {
                    Spacer()
                    NavigationLink(destination: CartView()
                        .environment(cartManager)
                    ) {
                        CartButton(numberOfProducts: cartManager.products.count)
                    }
                }
                Text("Shop for Beans")
                    .font(.largeTitle .bold())
            }
            
        }
        .padding()
        .environment(CartManager())
    }
}

CartButton.swift

import SwiftUI

struct CartButton: View {

    var numberOfProducts: Int
    
    var body: some View {
        ZStack(alignment: .topTrailing) {
            Image(systemName: "cart.fill")
                .foregroundStyle(.black)
                .padding(5)
            
            if numberOfProducts > 0 {
                Text("\(numberOfProducts)")
                    .font(.caption2).bold()
                    .foregroundStyle(.white)
                    .frame(width: 15, height: 15)
                    .background(Color(hue: 1.0, saturation: 0.89, brightness: 0.835))
                    .clipShape(RoundedRectangle(cornerRadius: 50))
            } 
        }
    }
}


#Preview {
    CartButton(/*numberOfProducts: 1*/numberOfProducts: 1)
}
Answered by KittyCat in 786681022

I figured it out! It turns out that when I called the .environment on the main app struct, I directly called CartManager() instead of cartManager. I think this is because of when I transitioned to the new Observed macro, I deleted the Object part of the .environmentObject that I had before, but I didn't change what was being called inside the parentheses.

Before:

After:

Figured out how to post a video:

https://gemoo.com/tools/upload-video/share/641405490124906496?codeId=vJ3lrB8A76mew&card=641405487482494976&origin=videolinkgenerator

This video demonstrates the error

Hi @KittyCat ,

I tried to replicate your issue using your above code and substituting in some things like Int for Product and was unable to reproduce this issue. I recommend going through your app and seeing if there's any other place that numberOfProducts gets set, since it must be getting set back to 0 at some point. One idea is printing the value in a few places in your app to see where it may be getting reset. For instance, you could use .onChange to print a message when it gets set to 0 and see where that may be happening.

Does anyone have any idea what's going on? I don't know why my changes to the array don't "save" whenever I switch views. This has been driving me insane for weeks

Accepted Answer

I figured it out! It turns out that when I called the .environment on the main app struct, I directly called CartManager() instead of cartManager. I think this is because of when I transitioned to the new Observed macro, I deleted the Object part of the .environmentObject that I had before, but I didn't change what was being called inside the parentheses.

Before:

After:

Shopping cart count disappears after changing tabs
 
 
Q