SwiftUI ForEach with index - "The compiler is unable to type-check this expression in reasonable time"

612 views Asked by At

In a swiftUI view that I'm writing, I need to use a ForEach, accessing each element of a list and its index. Most of the information I could find about this said to use .enumerated() as in ForEach(Array(values.enumerated()), id: \.offset) { index, value in }

However when I try to do that in my view:

/// A popover displaing a list of items.
struct ListPopover: View {
    // MARK: Properties
    /// The array of vales to display.
    var values: [String]
    
    /// Whether there are more values than the limit and they are concatenated.
    var valuesConcatenated: Bool = false
    
    /// A closure that is called when the button next to a row is pressed.
    var action: ((_ index: Int) -> Void)?
    /// The SF symbol on the button in each row.
    var actionSymbolName: String?
    
    // MARK: Initializers
    init(values: [String], limit: Int = 10) {
        if values.count > limit {
            self.values = values.suffix(limit - 1) + ["\(values.count - (limit - 1)) more..."]
            valuesConcatenated = true

        } else {
            self.values = values
        }
    }
    
    // MARK: Body
    var body: some View {
        VStack {
            ForEach(Array(values.enumerated()), id: \.offset) { index, value in
                HStack {
                    if !(index == values.indices.last && valuesConcatenated) {
                        Text("\(index).")
                            .foregroundColor(.secondary)
                    }

                    Text(value)
                    
                    Spacer()

                    if action != nil && !(index == values.indices.last && valuesConcatenated) {
                        Spacer()

                        Button {
                            action!(index)
                        } label: {
                            Image(systemName: actionSymbolName ?? "questionmark")
                        }
                        .frame(alignment: .trailing)
                    }
                }
                .if((values.count - index) % 2 == 0) { view in
                    view.background(
                        Color(.systemGray5)
                            .cornerRadius(5)
                    )
                }
            }
        }
    }
}

I get the error The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions on the line var body: some View {

I've also noticed that this code causes some other problems like making the Xcode autocomplete extremely slow.

Any ideas how I might be able to solve this? It seems like a pretty simple view and I think I'm doing the ForEach how I should.

Thanks!

1

There are 1 answers

7
Yrb On

This is a very misleading error. What it really means is you screwed something up in your body, but the compiler can't figure out the error, so it throws it on the body itself. The easiest way to find it is to comment out portions of your body in matched braces until the error goes away. In your case the issue is with this:

            .if((values.count - index) % 2 == 0) { view in
                view.background(
                    Color(.systemGray5)
                        .cornerRadius(5)
                )
            }

I am not sure what you are attempting to do, but .if is not valid syntax and I am not sure what view is or where it is supposed to come from.