Home > Net >  Trying to dynamically update swiftUI view
Trying to dynamically update swiftUI view

Time:08-11

struct MakeVideo: View {
    
    @EnvironmentObject var modelData: ModelData

    @State private var chosenFriends: [FriendModel] = []
    
    mutating func addFriend(_friend: FriendModel) -> Void {
        chosenFriends.append(_friend)
        
    }
    
    var body: some View {
        VStack {
            ForEach(modelData.friends) { friend in
                HStack {
                    ProfilePic(picture: friend.profilepic!)
                    Text("@" friend.username!)
                    
                    //TODO: This is updating the val, it just isn't being shown here
                    
                    Button("Add", action: friend.toggleChosen)
                    
                    if friend.isChosen {
                        Image(systemName: "star.fill")
                            .foregroundColor(.yellow)
                    } else {
                        Image(systemName: "star")
                    }
                    
                }
            }
        }
    }
}

struct MakeVideo_Previews: PreviewProvider {
    static var previews: some View {
        MakeVideo()
            .environmentObject(ModelData())
    }
}

I am trying to dynamically update this so that when ai click the Button, it'll make the star be filled instead of empty. In the debugger I see the class value being changed however the change does not appear in the view. I also made the var in the class @Published, which I thought would allow the view to change with the value

CodePudding user response:

try using this:

 ForEach($modelData.friends) { $friend in // <-- here $

CodePudding user response:

You don't say that you get a compiler error on the following line:

Button("Add", action: friend.toggleChosen)

Therefore I deduce that FriendModel is a class, not a struct. If FriendModel were a struct and toggleChosen were a mutating method, then you would get an error: “Cannot use mutating member on immutable value”.

Even if FriendModel conforms to ObservableObject, the problem is that ObservableObjects do not automatically compose. A change to an @Published property of a FriendModel will not be noticed by a containing ModelData, which means (in this case) that SwiftUI will not notice that friend.isChosen was modified.

I suggest making FriendModel into a struct.

I also recommend using Point-Free's Composable Architecture package (or something similar) as your app architecture, because it provides a comprehensive solution to problems like this.

CodePudding user response:

Body is only called for states that are used. Since chosenFriends is not used in body, it is not called when it is changed in a button action.

To fix, write a func isFriend and lookup the friend ID in the chosenFriends array and use the result of that in body to show the star. Since chosenFriends is now used, body will be called. Also change the button to call the addFriend func which would be better named as chooseFriend by the way.

  • Related