How to add and remove to favourites view on heart button press in swiftui

253 Views Asked by At

I have a struct and I displayed the product list screen from that struct.There is a heart button in product list view, I want to add the particular item to favourite view on button press and also button color needs to change.and also can remove the item from favourites while unfavourite it from product list screen. I have a user defaults, and I can see displayed, added and removed products in my console.but I have a problem with displaying it to favourite screen.can anyone please help me?

struct ProductModel : Codable {
    let productData : [ProductData]
    
    private enum CodingKeys:String,CodingKey {
        case productData = "data"
    }
}
struct ProductData : Identifiable,Codable,Hashable {
    var id : Int
    var title :String
    var type : String
    var description : String
    var filename : String
    var price : Float
    var rating : Int
    
    init() {
        self.id = 0
        self.title = ""
        self.type = ""
        self.description = ""
        self.filename = ""
        self.price = 0.0
        self.rating = 0
    }
   
}

this is my view model

import Foundation
class FavouriteViewModel : ObservableObject {
    @Published var isfavourite = false
    @Published var productData : [ProductData] = []
    // the products which user marked as favourites
    @Published var favourites = [ProductData]()
    let defaults = UserDefaults.standard
    var favItems : [ProductData] = []
    init() {
        guard let data = defaults.data(forKey: "Favourites") else {  return }
        self.favItems = (try? PropertyListDecoder().decode([ProductData].self, from: data)) ?? []
    }
    func getIds() -> [ProductData] {
        return self.favourites
    }
    func contains(productItem:ProductData) -> Bool {
        favourites.contains(productItem)
        
    }
    func addToFav(productItem:ProductData) {
        print("the add to fav called\(productItem)")
        favourites.insert(productItem, at: 0)
        favourites.append(productItem)
        save()
    }
    func removeFromFav(productItem:ProductData) {
        print("the remove from fav called\(productItem)")
        if let index = favourites.lastIndex(of: productItem) {
            favourites.remove(at: index)
        }
        save()
    }
    func save() {
        defaults.set(try? PropertyListEncoder().encode(favourites), forKey: "Favourites")
        getDataFromUserDefaults()
    }
    
    func getDataFromUserDefaults()  {
        guard let data = defaults.data(forKey: "Favourites") else {  return }
        self.favItems = (try? PropertyListDecoder().decode([ProductData].self, from: data)) ?? []
        print("the favourite data are \(favItems)")
        
    }
}

I have done these code in button pf product list screen

   import SwiftUI
import Kingfisher

struct ProductListView: View {
    
    @StateObject var favouriteViewModel : FavouriteViewModel = FavouriteViewModel()
    @State var item : String
    @State var filteredData : [ProductData]
    var body: some View {
        let columns = [GridItem(.flexible(minimum: 100,maximum: 150),spacing: 10),
                       GridItem(.adaptive(minimum: 100, maximum: 150),spacing: 10),
                       GridItem(.adaptive(minimum: 100, maximum: 150))]
        NavigationStack {
            ScrollView {
                LazyVGrid(columns: columns,spacing: 35) {
                    ForEach(filteredData,id: \.id) {
                        product in
                        NavigationLink(destination: DetailsCardView(productData: product),label: {
                            VStack(alignment: .center,spacing: 4){
                                KFImage(URL(string: product.filename))
                                    .resizable()
                                    .frame(width: 50,height: 50,alignment: .center)
                                    .scaledToFill()
                                Text(product.title)
                                    .font(.system(size: 10,weight: .semibold))
                                    .foregroundColor(.black)
                                HStack(spacing: 40) {
                                    Text("\(product.price,specifier: "%.2f")/1Kg")
                                        .font(.system(size: 9,weight: .regular))
                                        .foregroundColor(.black)
                                    Button(action: {
                                        if self.favouriteViewModel.contains(productItem: product) {
                                            self.favouriteViewModel.removeFromFav(productItem: product)
                                        } else {
                                            self.favouriteViewModel.addToFav(productItem: product)
                                        }
                                    }) {
                                        Image(favouriteViewModel.contains(productItem: product) ? "heartfill" : "heart")
                                            .frame(alignment: .bottomTrailing)
                                    }
                                }
                                
                            }
                            
                        }
                                       
                        ) }
                    
                    .overlay(
                        RoundedRectangle(cornerRadius: 20,style: .circular)
                            .stroke(Color.gray,lineWidth: 0.3)
                            .shadow(radius: 1)
                            .frame(width: 115,height: 120)
                    )
                }
                .padding(15)
            }
            .navigationBarTitle(Text(item),displayMode: .inline)
        }
    }
}

this is my favourite view

import SwiftUI
import Kingfisher
struct FavouriteView:View {
   
    @ObservedObject var favouriteViewModel : FavouriteViewModel = FavouriteViewModel()
    var body: some View {
        NavigationStack {
                List {
                    ForEach(favouriteViewModel.favItems) { item in
                    ZStack {
                        RoundedRectangle(cornerRadius: 20,style: .circular)
                            .fill(.white)
                            .shadow(radius: 1)
                            .frame(width: 360,height: 120)
                        
                        HStack(spacing:10){
                            KFImage(URL(string: item.filename))
                                .resizable()
                                .frame(width: 50,height: 50)
                                .scaledToFit()
                                .padding(.leading,20)
                            
                            VStack(alignment: .leading,spacing: 10) {
                                Text(item.title)
                                Text("\(item.price,specifier: "%.2f")/1Kg")
                                    .foregroundColor(Color.gray)
                            }
                            Spacer()
                           Image(favouriteViewModel.contains(productItem: item) ? "heart" : "heartfill")
                                    .padding(.trailing,10)
                            
                            }
                        }
                    }
                    .onAppear {
                        favouriteViewModel.getDataFromUserDefaults()
                        //favouriteViewModel.addToFav(productItem: ProductData())
                        //favouriteViewModel.removeFromFav(productItem: ProductData())
                    }
                   
                }
                .frame(maxWidth: .infinity)
                .edgesIgnoringSafeArea(.horizontal)
                .listStyle(GroupedListStyle())
                    
                }
              
            .navigationBarTitle(Text("Favourites"),displayMode: .inline)
        }
    }
0

There are 0 best solutions below