Currently since its in a ForEach loop and i only have one State var, when i press follow they all change to following. I used a ternary operator to make the button color and text switch if the isFollowing is toggled. How would i go about making it toggle only for a specified user when the button is clicked. Would i just need to make 3 buttons outside the loop? When i used user.isFollowingUser.toggle in the button it tells me that I cant mutate user.
import SwiftUI
struct InstagramModel: Identifiable{
let id: String = UUID().uuidString
let username: String
let userImage: String
let followers: Int
let isVerified: Bool
let isFollowingUser: Bool
}
struct ModelPractice: View {
@State private var users: [InstagramModel] = [
InstagramModel(username: "aleedagenie", userImage: "AliImage", followers: 490, isVerified: true, isFollowingUser: false),
InstagramModel(username: "nicole29", userImage: "volcano2", followers: 1090, isVerified: true, isFollowingUser: false),
InstagramModel(username: "shamat81", userImage: "crashedCar", followers: 290, isVerified: false, isFollowingUser: false)
]
@State private var isFollowing: Bool = false
@State private var isShowDialog: Bool = false
@State private var background: Color = .mint
var body: some View {
NavigationView{
VStack{
List{
Section {
ForEach(users) { user in
VStack(alignment: .leading) {
HStack {
Image(user.userImage)
.resizable()
.frame(width: 35, height: 35)
.clipShape(Circle())
VStack(alignment: .leading) {
Text(user.username)
.font(.headline)
HStack {
Text("Followers:")
.font(.caption)
Text("\(user.followers)")
.font(.caption)
}
}
Spacer()
if user.isVerified{
Image(systemName: "checkmark.seal.fill")
.foregroundColor(.blue)
}
}
Button {
isFollowing.toggle()
} label: {
Text(isFollowing ? "Following" : "Follow")
.foregroundColor(isFollowing ? .black: .white)
.frame(maxWidth: 90)
.background(isFollowing ? .white: .blue)
.cornerRadius(12)
}
.padding(.horizontal, 44)
}
}
} header: {
Text("Instagram Users")
}
.listRowBackground(background)
}
Button {
isShowDialog.toggle()
} label: {
Text("Change Page Style")
.bold()
.frame(maxWidth: 140)
.background(.orange)
.cornerRadius(20)
}
.confirmationDialog("Text", isPresented: $isShowDialog, actions: {
Button {
background = .yellow
} label: {
Text("Option 1")
}
Button {
background = .gray
} label: {
Text("Option 2")
}
Button {
background = .green
} label: {
Text("Option 3")
}
})
.navigationTitle("Instagram")
}
}
}
}
struct ModelPractice_Previews: PreviewProvider {
static var previews: some View {
ModelPractice()
}
}
CodePudding user response:
The problem here is you are trying to mutate the variable of closure called user. user is a temporary variable which is not linked with your users, so you can't mutate it.
Instead you should mutate the users.
Here is my demo, try it out. Code is below the image:
struct UserModel: Identifiable {
var id = UUID()
var name: String = ""
var following = false
}
struct DemoView: View {
@State var listUser = [
UserModel(name: "Lamb Chop", following: false),
UserModel(name: "Steak", following: false)
]
var body: some View {
List {
ForEach(listUser.indices) { index in
HStack {
Text(listUser[index].name)
Button {
listUser[index].following.toggle()
} label: {
Text(listUser[index].following ? "following" : "follow")
}
.padding(5)
.background(.black)
.cornerRadius(15)
}
}
}
}
}

