Linas
Linas

Reputation: 75

SwiftUI Mathematical operations inside (some View)

I'd like to ask you a question about the usage of mathematical operations inside the view.

struct MyMenu: View {
    var cnt: Int = 0
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        ForEach(colors, id: \.self) { color in
            Text(color.description)
                .padding()
                .background(color)

            cnt += 1
        }
    }
}

It gives me an error:

Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols

I do not understand what's wrong with SWIFTUI syntax? Why simple mathematical operations cannot be used inside the some View.

Any solution? Thank you!

Upvotes: 2

Views: 1520

Answers (4)

Metatron
Metatron

Reputation: 31

I have been struggling with this problem too! The .onAppear doesn't help because although it counts the number of times they appear during initialisation, you can't index the elements with it, because it will only use the last number. So I outsourced the Text generation to a module where I put an inout parameter and the module can already work with index += 1. This is important if you have an array matrix with unequal number of elements in the row, so afterwards row*col will not give the correct index number.

The code looks like this, it works ... but SwiftUI sometimes behaves strangely, so I prefer to add the indexes to the matrix already at generation time.

var matrix = [ ["a0", "a1", "a2"] , ["b0", "b1"] , ["c0", "c1", "c2", "c3"] ]

var body: some View {
    
    var index = 0
    
    LazyVStack(alignment: .trailing) {
        ForEach(0..<matrix.count, id: \.self) { row in
            ForEach(0..<matrix[row].count, id: \.self) { col in
                
                TextBlock( &index, matrix[row][col] )
            }
        }
    }


func TextBlock(_ index: inout Int, _ data: String) -> some View {
    
    index += 1
    
    return Text("\(index): \(data)")
}

Upvotes: 0

Romez
Romez

Reputation: 1

you can get the counter with the .count function like this :

struct MyMenu: View {

let colors: [Color] = [.red, .green, .blue]
var cnt: Int = colors.count

var body: some View {
    ForEach(colors, id: \.self) { color in
        Text(color.description)
            .padding()
            .background(color)
            
     }
   } 
 }

Upvotes: -1

Jonas Deichelmann
Jonas Deichelmann

Reputation: 3743

If you really need to do it in the SwiftUI Body, you can do it with the .onAppear() Modifier, but as @UIChris pointed out, SwiftUI is expecting to have declarative code to generate just the UI.

Your code would look like that:

struct MyMenu: View {
    var cnt: Int = 0
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        ForEach(colors, id: \.self) { color in
            Text(color.description)
                .padding()
                .background(color)
                .onAppear(){
                    cnt += 1
                }
         }
     }
}

Upvotes: 0

UIChris
UIChris

Reputation: 621

You cannot have "regular" code inside you body, as SwiftUI is expecting you to have declarative code to generate the UI in there.

If you would like to increment your cnt property, you need to do it inside a button action for example, like so:

Button(action: {
    cnt += 1
}) {
    Text("Click me to perform any action")
}

Don't forget that your MyMenu object is a struct meaning that by default, it is immutable. You will not be able to update your cnt property if it isn't wrapped with the @State wrapper, or any other depending on your needs :)

Hope this helps! :)

Upvotes: 2

Related Questions