Home > Software engineering >  Altering property in a SwiftUI ForEach loop
Altering property in a SwiftUI ForEach loop

Time:12-11

I have been trying to change the offset value of an object in SwiftUI, but can't quite get it to work. I feel like there's something basic I'm missing here.

Below is the main SwiftUI code. I am trying to change the offset value of each card in a stack as the user swipes. However, on line with "user.offset = value.translation.width", I get the error "Cannot assign to property: 'user' is a 'let' constant". I think I understand that that is because you are not actually able to change the object you are iterating through with a ForEach loop. However, I'm struggling to find a workaround.

import SwiftUI
import Kingfisher

struct GroupSessionView: View {
    @ObservedObject var userViewModel = ExploreUsersViewModel()
   
    var body: some View {
        VStack(spacing: 10) {
            ZStack {
                ForEach(Array(zip(userViewModel.userCards.indices, userViewModel.userCards)), id: \.0) { index, user in
                    HStack {
                        KFImage(URL(string: user.image))
              
                    }
                    .zIndex(Double(userViewModel.users.count - index))
                    .offset(x: 0)
                    .gesture(DragGesture().onChanged({ value in
                        withAnimation {
                            user.offset = value.translation.width
                        }
                    }).onEnded({ (value) in
                        withAnimation {
                            user.offset = 0
                        }

                    }))
                           
                }
            }
            Spacer()
        }
    }
}

And here is the view model I am working with to produce the userCards data.

class ExploreUsersViewModel: ObservableObject {
    @Published var users = [User]()
    @Published var userCards = [UserCard]()
    let service = UserService()
    
    init() {
        fetchUsers()
        getCards()
    }
    
    func fetchUsers() {
        service.fetchUsers { users in
            self.users = users
            
            print("Users are \(users)")
        }
    }
    
    func getCards() {
        service.fetchUsers { users in
            for user in users {
                self.userCards.append(UserCard(id: NSUUID().uuidString, image: user.profileImageUrl, fullName: user.fullname, offset: 0))
            }
        }
    }
}

CodePudding user response:

In ForEach (as well as forEach) all index variables are constants.

But as you have the index the solution is pretty easy: Modify the item in the array directly

userViewModel.userCards[index].offset = value.translation.width
  • Related