How to assign a variable in e.g. a ForEach in SwiftUI?

2.3k views Asked by At

is it possible to set a variable in SwiftUI e.g. in a ForEach like this:

struct ContentView: View {
    var test: Int

    var body: some View {

        List {
            ForEach(1...5, id: \.self) {
                Text("\($0)…")

                test = $0 // how to realise this?
            }
        }

    }
}

I can not bring this to live, I'm getting an error like:

Unable to infer complex closure return type; add explicit type to disambiguate
2

There are 2 answers

0
Axel Schmitz On

What you can do is using a @State var definition and apply the value from a task inside your foreach. Example:

struct MyView: View {

@State var curGameDate: String = ""
var gameSection: GameSectionDto

var body: some View {

       Text(curGameDate) // <- use the state var outside the loop
                .padding(.bottom, 2.0)
                .padding(.horizontal, 10.0)
                .foregroundColor(Color("DarkGrey"))
                .font(.system(size: 15.0))
                .frame(maxWidth: .infinity, alignment: .leading)


    ForEach(gameSection.listItems, id: \.gameIdentifier) { game in
        GeometryReader { proxy in
            GameRowView(game: game, isResult: gameSection.result)
                    .background(RoundedCorners(color: .white, tl: 10, tr: 10, bl: 10, br: 10))
                    .padding([.leading, .trailing], 5.0)
                    .rotation3DEffect(.degrees(proxy.frame (in: .global).minX / -10), axis: (x: 0, y: 1, z: 0))
                    .shadow(color: .black.opacity(0.3),
                            radius: 8, x: 0, y: 6)
        } //: GeoReader
                .padding([.leading, .trailing], 5.0)
                .padding(.top, 5.0)
                .padding(.bottom, 25.0)
                .task { // assign it in the foreach
                    self.curGameDate = game.gameDate.getDateString(pattern: "eeee, dd.MM.yyyy")
                } //: task

    } //: ForEach
    
}

}

0
Asperi On

You cannot assign to test anything from anywhere inside your ContentView, because it is struct and, so, self is immutable, but you will be able to do something like in the following:

struct ContentView: View {
//    var test: Int // cannot be assigned, because self is immutable

    var body: some View {
        List {
            ForEach(1...5, id: \.self) { (i) -> Text in
                let test = i // calculate something intermediate
                return Text("\(test)…")
            }
        }
    }
}