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