Compile error, doing calculations in View body

Hi,

I'm trying to show a number of buttons of a certain relative size to the screen width. For now I'm hard-coding the number of buttons, just to get the collection view wrap style working.

I'm getting the Xcode error:

The compiler is unable to type-check this expression in reasonable time

It seems obvious that doing the indexing calculations probably cause the problem. But I don't know how to do that calculation once per iteration, and store the value.

It worked fine, compiled, and ran in preview mode a couple of times. Then with no changes it just stopped compiling, and Xcode gave the error.

Any suggestions as to what can I do? Eventually I want to use the index calculation to subscript an array value.

Code Block
struct collectionView: View {
    let totalElements = 5
    let rowCount = 2
    let rowLength = 3
    var body: some View {
        GeometryReader<AnyView> { geometry in
            return AnyView(
                VStack(alignment: .leading) {
                    ForEach(0..<self.rowCount) { rowIndex in
                        HStack {
                            ForEach(0..<self.rowLength) { elementIndex in
                                if ((rowIndex * self.rowLength) + elementIndex < self.totalElements) {
                                    Button(action: {
                                        print(msg: "\((rowIndex * self.rowLength) + elementIndex)")
                                    }) {
                                        Text("\( (rowIndex * self.rowLength) + elementIndex)")
                                    }
                                    .background(Color.purple)
                                    .foregroundColor(Color.white)
                                }
                            } // ForEach elementIndex
                        } // HStack
                    } // ForEach rowIndex
                } // VStack
            ) // AnyView
        } // GeometryReader
    }
}



Accepted Reply

hi,

two things on syntax will make this compile (Xcode 11.6):
  • line 16: remove the msg: label ... there is no label for print().

  • lines 20-21: move these as modifiers onto the Text in line 18, inside the closing brace on line 19.

hope that helps,
DMG

Replies

hi,

two things on syntax will make this compile (Xcode 11.6):
  • line 16: remove the msg: label ... there is no label for print().

  • lines 20-21: move these as modifiers onto the Text in line 18, inside the closing brace on line 19.

hope that helps,
DMG
Ach, my obvious mistake on the first one. I had been using a separate custom log method, which did have a label.

On the second, ahh yes I see. Compiled first time with the changes.

thanks very much,
For anyone happening upon this, here's the working version. In my case I'm drawing a collection of buttons.

Code Block
struct collectionView: View {
    let totalElements = 8
    let elementWidth: CGFloat = 80.0
    var body: some View {
        GeometryReader<AnyView> { geometry in
            let elementsPerRow = Int(geometry.size.width / self.elementWidth)
            let rowCount = Int( (CGFloat(self.totalElements) / CGFloat(elementsPerRow)).rounded(.up) )
            return AnyView(
                VStack(alignment: .leading) {
                    ForEach(0..<rowCount) { rowIndex in
                        HStack {
                            ForEach(0..<elementsPerRow) { elementIndex in
                                if ((rowIndex * elementsPerRow) + elementIndex < self.totalElements) {
                                    Button(action: {
                                        print("\((rowIndex * elementsPerRow) + elementIndex)")
                                    }) {
                                        Text("\( (rowIndex * elementsPerRow) + elementIndex)")
                                        .frame(maxWidth: self.elementWidth, maxHeight: self.elementWidth)
                                        .background(Color.purple)
                                        .foregroundColor(Color.white)
                                        .clipShape(Circle())
                                    }
                                }
                            }
                        }
                    }
                }
            )
        }
    }
}