I tried to bind the property to as isFavorite, somehow its value is changing on change but the view is not changing though.
@EnvironmentObject var modelData: ModelData
var landmark:Landmark
var landmarkIndex: Int {
modelData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}
var body: some View {
ScrollView{
MapPreview(coordinate: landmark.locationCoordinate)
.ignoresSafeArea(edges: .top)
.frame(height: 300)
MapProfileImage(image: landmark.image)
.offset(y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading){
HStack{
Text(landmark.name)
.font(.largeTitle)
FavoriteButton(isSet: $modelData.landmarks[landmarkIndex].isFavorite)
}
HStack{
Text(landmark.park)
Spacer()
Text(landmark.state)
}
and its binded to a property isSet
struct FavoriteButton: View {
@Binding var isSet: Bool
var body: some View {
Button(action: {
print("isSet \(String(isSet))")
isSet.toggle()
}){
Image(systemName:isSet ? "star.fill" : "star")
.foregroundColor(.black)
}
}
}
Im new to SwitftUI, care to explain whats wrong pls
CodePudding user response:
Usually @Binding
is used when you want to bind a @State
property in the parent view with another property in the child view.
In your case, you already have your view model in the environment, so just need to read the the environment again in the child view and change the variable directly there.
Here is how you could implement FavoriteButton
:
struct FavoriteButton: View {
// Read the environment to get the view model
@EnvironmentObject var modelData: ModelData
// You will need to pass the index from the parent view
let index: Int
var body: some View {
Button(action: {
print("index \(index), isSet \(String(modelData.landmarks[index].isFavorite))")
// Change the view model directly
modelData.landmarks[index].isFavorite.toggle()
}){
Image(systemName: modelData.landmarks[index].isFavorite ? "star.fill" : "star")
.foregroundColor(.black)
}
}
}
In the parent view, call it passing the index:
FavoriteButton(index: landmarkIndex)
Needless to say, ModelData
needs to be a class
that conforms to ObservableObject
and must already be in the environment when you call the parent view.