Learn Courses My Dashboard

Displaying issue with Favorites TabView

I’m having an issue with my FavoritesTab. It’s a bit difficult to explain so I posted a video to show what’s the ongoing issue. In short, once I favorite a character, and go to the FavoritesTab, it will display a duplicate. Then trying to switch back and forth between tabs will remove the display and then (again) finally will display appropriately. Please let me know if you need any additional code

ezgif.com-gif-maker (2)

I have environmentObject modifiers of my ViewModel and Favorites on CharactersTabView which is the @Main entry view for my app.

struct CharactersTabView: View {
   


    var body: some View {
        TabView {
            
            //MARK: - Character Tab
            CharacterView()
                .tabItem {
                    Label("Characters", systemImage: "person.3.fill")
                }
            
            
    
            //MARK: - Favorites Tab
            FavoritesView()
                .tabItem {
                    Label("Favorites", systemImage: "heart.fill")
                }
        }//TabView
       
              
    }
}

Here is my Favorites code

class Favorites: ObservableObject {
    private var characters: Set<String>

    private let saveKey = "SaveFavorites"
    
    init(){
        //load saved data
        if let data = UserDefaults.standard.data(forKey: saveKey) {

            
            //Using Set<String> because we don't want to store the entire struct, just the id
            if let decoded = try? JSONDecoder().decode(Set<String>.self, from: data) {
                characters = decoded
                return
            }
        }
        characters = []
    }
    
    
    func contains(_ character: Character) -> Bool {
        characters.contains(String(character.id))
    }
    
    func add(_ character: Character) {
        objectWillChange.send()
        characters.insert(String(character.id))
        save()
    }
    
    func remove(_ character: Character) {
        objectWillChange.send()
        characters.remove(String(character.id))
        save()
    }
    
    
    func save(){
        if let encoded = try? JSONEncoder().encode(characters) {
            UserDefaults.standard.set(encoded, forKey: saveKey)
        }
    }
}

And here is my FavoritesView

struct FavoritesView: View {
    
    @EnvironmentObject var model: CharacterViewModel
    @EnvironmentObject var favorites: Favorites
    //Creating the property of the same type (Favorites) can access the data and get updated when the data changes
  
    var body: some View {
        
       
        NavigationView {
            List(model.filteredCharacters) { character in
                if favorites.contains(character) {

                    NavigationLink {
                        CharacterDetailsView(character: character)
                    } label: {
                        HStack {
                            CharacterRowView(imageUrlString: character.image, name: character.name, species: character.species)
                        }
                    }
                }
            }
            .navigationTitle("Favorites")
        }
    }
}

Here is my other TabView of Character for reference

struct CharacterView: View {
    @EnvironmentObject var model: CharacterViewModel
    @EnvironmentObject var favorites: Favorites
    //Creating the property of the same type (Favorites) can access the data and get updated when the data changes
    


    //MARK: - Body
    var body: some View {
        
        NavigationView {
          
            List(model.filteredCharacters){
                   character in
                        
                        NavigationLink {
                            CharacterDetailsView(character: character)
                        } label: {
                            HStack{
                                CharacterRowView(imageUrlString: character.image, name: character.name, species: character.species)
                                
                                if favorites.contains(character) {
                                    Spacer()
                                    Image(systemName: "heart.fill")
                                        .accessibilityLabel("This is a favorite character")
                                        .foregroundColor(.red)
                                }
                            }
                        
                        }
            }
            .searchable(text: $model.searchText, prompt: "Search for a character")
            .onChange(of: model.searchText, perform: { newValue in
                    Task {
                        await model.fetchallCharacters()
                     }
            })
            .navigationBarTitle("Characters")
        }//Navigationview
        .task({
            await model.fetchallCharacters()
        })
        .phoneOnlyNavigationView()

    }
}

I’m still having issues with this situation. Any thoughts/suggestions would be appreciated.