I'm running into an issue I can't figure out. How do you save the color of a button once a user clicks on it and have it switch back when the uncheck it? I have a Favorites button that when a user clicks on it, the color, SF symbol, and text changes from "Favorite" to "Favorited". That works fine. However, when I leave the screen, everything goes back to the original colors.
Here is my code.
import SwiftUI
struct CharacterDetailsView: View {
//Need to reference for detail view by relying on the list to assign the details.
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)
Section {
SubDetailView(sfImageString: "checkmark.circle", infoText: "Status", detailText: character.status)
SubDetailView(sfImageString: "person.circle", infoText: "Species", detailText: character.species)
SubDetailView(sfImageString: "house.circle", infoText: "Origin", detailText: character.origin.name)
SubDetailView(sfImageString: "mappin.circle", infoText: "Location", detailText: character.location.name)
}
.padding(.horizontal)
}
favoriteButton
}
}
}
}
CodePudding user response:
You need to restore state from environment object where you stored provious one, like
favoriteButton
.onAppear {
isFavorite = favorites.contains(character) // << here !!
}