Search code examples
iosswiftswiftuiswiftui-environmentswiftui-button

How do I persist the button color after favoriting in SwiftUI?


I would like my favorites button to switch colors based on if the user favorites or unfavorites a character. I am able to change the text from "Favorite" to "Favorited" and change the color initially. If I exit the app, the button color goes back to the original color. I have logic in my computed property for the color to change but don't know how to persist it when the user open and closes the app.

Here is my code.

import SwiftUI

struct CharacterDetailsView: View {
    
   
 var character: Character
    
    @EnvironmentObject var favorites: Favorites
   
    
    @State private var isFavorited = false
  
    
    
    var favoriteText: String {
        if isFavorited  {
            return "Favorited"
        } else {
            return "Favorite"
        }
    }
    
    var favoriteButton: some View {
        Button {
            isFavorited.toggle()
           
            
            if favorites.contains(character) {
                //If favorites contains a character, we are trying to un-favorite and remove it
                favorites.remove(character)
            } else {
                favorites.add(character)
            }
           
        } label: {
            ZStack {
                if isFavorited == false {
                    Capsule()
                        .strokeBorder(Color.green, lineWidth: 4)
                        .frame(width: 250, height: 50)
                        .background(
                            Capsule()
                                .fill(.green)
                                .cornerRadius(20)
                        )
                
                } else {
                    Capsule()
                        .strokeBorder(Color.blue, lineWidth: 4)
                        .frame(width: 250, height: 50)
                        .background(
                        Capsule()
                            .fill(.blue)
                            .cornerRadius(20)
                        )
                        
                }
                
                HStack {
                    Text(favoriteText)
                        .foregroundColor(.white)
                    Image(systemName: favorites.contains(character) ? "heart.fill" : "heart")
                        .foregroundColor(favorites.contains(character) ? .white : .white)
                        
                }
            }
        }
        .padding(.vertical)
    }
 
    
    var body: some View {
        ScrollView {
            VStack {
                //MARK: - Image
                AsyncImage(url: URL(string: character.image)) {
                    phase in
                    if let image = phase.image {
                        image
                            .resizable()
                            .scaledToFit()
                    } else if phase.error != nil {
                        Text("Couldn't upload photo")
                    } else {
                        ProgressView()
                    }
                }
            

                VStack(alignment: .leading) {
                    Text(character.name)
                        .font(.largeTitle)
                        .bold()
                        .padding(.leading)
                       
                    

            favoriteButton
    
            }
        }
       
    }
    
    
  
}

Solution

  • You need to restore state from environment object where you stored provious one, like

    favoriteButton
       .onAppear {
          isFavorite = favorites.contains(character)    // << here !!
       }