quirky purple
quirky purple

Reputation: 2219

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

I’m trying to build what I thought was a simple form in SwiftUI, but am getting the error “The compiler is unable to type check this expression; try breaking up the expression into distinct sub sections” on the view being returned from the body (in this case Form, but I’ve also tried VStack). If I start removing some of the subviews, it seems to resolve, even though none of my views directly returns 10 subviews, which I believe is the limit for a single view (except for views returned in ForEach).

import SwiftUI

struct CreateDispatchView: View {
    @State private var customerId: Int = 0
    @State private var name: String = ""
    @State private var phone: String = ""
    @State private var description: String = ""
    @State private var priorityId: Int = 0
    @State private var callTypeId: Int = 0
    @State private var bay: String = ""
    @State private var poTicket: String = ""
    @State private var outOfChemicals: Bool = false
    @State private var isReturnCall: Bool = false

    var body: some View {
        Form { // <-- Error is shown here
            Section {
                Picker("Customer", selection: $customerId) {
                    ForEach(0 ..< 10) {
                        Text("Customer \($0)")
                    }
                }
                TextField("Name", text: $name)
                TextField("Phone", text: $phone)
                TextField("Description", text: $description)
                TextField("Bay", text: $bay)
                TextField("PO ticket", text: $poTicket)
            }

            Section {

                Picker("Priority", selection: $priorityId) {
                    ForEach(0 ..< 2) {
                        Text("Priority \($0)")
                    }
                }
                Picker("Call type", selection: $callTypeId) {
                    ForEach(0 ..< 3) {
                        Text("Call type \($0)")
                    }
                }
            }

            Section {

                Toggle(isOn: $outOfChemicals) {
                    Text("Out of chemicals")
                }
                Toggle(isOn: $isReturnCall) {
                    Text("Is return call")
                }
            }
        }
    }
}

struct CreateDispatchView_Previews: PreviewProvider {
    static var previews: some View {
        CreateDispatchView()
    }
}




Upvotes: 3

Views: 2311

Answers (1)

marcprux
marcprux

Reputation: 10355

The handling of large nested ViewBuilder expressions is a weak point in the current swift compiler. Generally speaking, though, its advice to "try breaking up the expression into distinct sub sections" is a good one: refactoring these monolithic ViewBuilder expressions out into separate dynamic variables is a good way to improve performance (plus it helps in isolating actual errors).

Here's an example of how you might refactor your code to compile successfully:

struct CreateDispatchView: View {
    @State private var customerId: Int = 0
    @State private var name: String = ""
    @State private var phone: String = ""
    @State private var description: String = ""
    @State private var priorityId: Int = 0
    @State private var callTypeId: Int = 0
    @State private var bay: String = ""
    @State private var poTicket: String = ""
    @State private var outOfChemicals: Bool = false
    @State private var isReturnCall: Bool = false

    var body: some View {
        Form {
            customerSection
            prioritySection
            infoSection
        }
    }

    private var customerSection: some View {
        Section {
            Picker("Customer", selection: $customerId) {
                ForEach(0 ..< 10) {
                    Text("Customer \($0)")
                }
            }
            TextField("Name", text: $name)
            TextField("Phone", text: $phone)
            TextField("Description", text: $description)
            TextField("Bay", text: $bay)
            TextField("PO ticket", text: $poTicket)
        }
    }

    private var prioritySection: some View {
        Section {
            Picker("Priority", selection: $priorityId) {
                ForEach(0 ..< 2) {
                    Text("Priority \($0)")
                }
            }
            Picker("Call type", selection: $callTypeId) {
                ForEach(0 ..< 3) {
                    Text("Call type \($0)")
                }
            }
        }
    }

    private var infoSection: some View {
        Section {
            Toggle(isOn: $outOfChemicals) {
                Text("Out of chemicals")
            }
            Toggle(isOn: $isReturnCall) {
                Text("Is return call")
            }
        }
    }
}

Upvotes: 4

Related Questions