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()
func calculateWidth() -> CGFloat {
let screen = UIScreen.main.bounds.width - 50
let width = screen - (2*60)
return width
}
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))
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: calculateWidth(), height: (UIScreen.main.bounds.height / 3.5) - CGFloat(index*30))
.cornerRadius(15)
.offset(x: index <= 2 ? CGFloat(index * 30): 60)
}
.zIndex(Double(userViewModel.users.count - index))
.contentShape(Rectangle())
.offset(x: 0)
.gesture(DragGesture().onChanged({ value in
withAnimation {
user.offset = value.translation.width
}
}).onEnded({ (value) in
withAnimation {
user.offset = 0
}
}))
}
}
.frame(height: UIScreen.main.bounds.height / 3.5)
.padding(.horizontal)
.padding(.top)
Spacer()
}
.padding(.top)
}
}
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))
}
}
}
}
>Solution :
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
users[index].offset = value.translation.width