Search code examples
foreachswiftuiios13

Update @State variable (Int Counter) through ForEach button not possible?


Trying to update the counter by iterating through ForEach button but receive the following error in Xcode 11:

Cannot convert value of type >'ForEach, >_ModifiedContent)>>, >PaddingLayout>>' to closure result type ''

Have tried adding @State but still unable to update count in var characterList

import SwiftUI

struct CharacterSelection:Identifiable {
    var id: Int
    var name : String
    var count: Int
}
import SwiftUI

struct ContentView : View {

    @State var charactersList = [
        CharacterSelection(id: 0, name: "Witch", count: 0),
        CharacterSelection(id: 1, name: "Seer", count: 1),
        CharacterSelection(id: 2, name: "Hunter", count: 0),
        CharacterSelection(id: 3, name: "Knight", count: 0)
    ]


    var body: some View {

        VStack(alignment:.leading) {
            ForEach(charactersList.identified(by: \.id)) {character in
                HStack{
                    Text(character.name)
                    Spacer()
                    Text("\(character.count) 

                    Button(action: { character.count += 1 }) {
                        Text("Button")
                    }

                }.padding(10)
            }
        }
    }
}

The count in respective index in var CharacterList should += 1 when the button is tapped.


Solution

  • Note that both Arrays and CharacterSelection are Value types, not Reference types. If you don't know the difference, check this page: https://developer.apple.com/swift/blog/?id=10

    For your code to work, you can rewrite it like this:

    struct ContentView : View {
    
        @State var charactersList = [
            CharacterSelection(id: 0, name: "Witch", count: 0),
            CharacterSelection(id: 1, name: "Seer", count: 1),
            CharacterSelection(id: 2, name: "Hunter", count: 0),
            CharacterSelection(id: 3, name: "Knight", count: 0)
        ]
    
    
        var body: some View {
    
            VStack(alignment:.leading) {
                ForEach(0..<charactersList.count) { i in
                    HStack{
                        Text(self.charactersList[i].name)
                        Spacer()
                        Text("\(self.charactersList[i].count)")
    
                        Button(action: { self.charactersList[i].count += 1 }) {
                            Text("Button")
                        }
    
                    }.padding(10)
                }
    
                Button(action: {
                    self.charactersList.append(CharacterSelection(id: self.charactersList.count, name: "something", count: 0))
                }, label: {
                    Text("Add CharacterSelection")
                })
    
            }
        }
    }