Learn Courses My Dashboard

SwiftUI List Limits and Groups

Hi there, it seems that a List is limited to 10 view items in it. I found the suggestion on the internet to place items in a Group { }. In one of my Lists this worked, but in the other List I keep on getting the message:

The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

even though the number of items is only 8. The items are a limited number which do not make sense to place in an array and to use a ForEach in the List. Any suggestions?

Post some code so we can see what’s going on and offer help. That’s rather hard to do if we don’t know what you are doing that’s causing errors.

The code are as follows. There are 8 HStack sections in the list:

    List {
        
        Group {
            
            HStack(alignment: .bottom) {
                Text("Altitude:")
                Spacer()
                Picker(units.altitudeUnit[altitudeUnitIdx],
                       selection: $altitudeUnitIdx) {
                    
                    ForEach(0..<units.altitudeUnit.count, id: \.self) { idx in
                        Text(units.altitudeUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
            }
            
            HStack(alignment: .bottom) {
                Text("Distance:")
                Spacer()
                Picker(units.distanceUnit[distanceUnitIdx2],
                       selection: $distanceUnitIdx2) {
                    
                    ForEach(0..<units.distanceUnit.count, id: \.self) { idx in
                        Text(units.distanceUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
                .onChange(of: distanceUnitIdx2, perform: { value in
                    model.units.distanceUnitIdx = value
                })
            }
            
            HStack(alignment: .bottom) {
                Text("Fuel consumption:")
                Spacer()
                Picker(units.consumptionUnit[consumptionUnitIdx],
                       selection: $consumptionUnitIdx) {
                    
                    ForEach(0..<units.consumptionUnit.count, id: \.self) { idx in
                        Text(units.consumptionUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
                
            }
            
            HStack(alignment: .bottom) {
                Text("Fuel volume:")
                Spacer()
                Picker(units.fuelUnit[fuelUnitIdx],
                       selection: $fuelUnitIdx) {
                    
                    ForEach(0..<units.fuelUnit.count, id: \.self) { idx in
                        Text(units.fuelUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
                
            }
        }
        
        Group {
            HStack(alignment: .bottom) {
                Text("Mass:")
                Spacer()
                Picker(units.massUnit[massUnitIdx],
                       selection: $massUnitIdx) {
                    
                    ForEach(0..<units.massUnit.count, id: \.self) { idx in
                        Text(units.massUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
                
            }
            
            HStack(alignment: .bottom) {
                Text("Speed:")
                Spacer()
                Picker(units.speedUnit[speedUnitIdx],
                       selection: $speedUnitIdx) {
                    
                    ForEach(0..<units.speedUnit.count, id: \.self) { idx in
                        Text(units.speedUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
            }
            
            HStack(alignment: .bottom) {
                Text("Temperature:")
                Spacer()
                Picker(units.temperatureUnit[temperatureUnitIdx],
                       selection: $temperatureUnitIdx) {
                    
                    ForEach(0..<units.temperatureUnit.count, id: \.self) { idx in
                        Text(units.temperatureUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
            }
            
            HStack(alignment: .bottom) {
                Text("Rate of climb:")
                Spacer()
                Picker(units.climbUnit[climbUnitIdx],
                       selection: $climbUnitIdx) {
                    
                    ForEach(0..<units.climbUnit.count, id: \.self) { idx in
                        Text(units.climbUnit[idx]).tag(idx+1)
                    }
                }
                .pickerStyle(MenuPickerStyle())
                .foregroundColor(Color.black)
                
            }
        }
        
    }.navigationBarTitle("Units")

You have a lot of code that is exactly the same except for which member of units gets looped over and the label applied. You should extract a View from that code and use it. That will reduce the complexity that Xcode has to deal with.

What does your units struct/class look like?

Tip: You should use three backticks ``` to enclose your code. You have used three periods ... instead. Or maybe even an ellipsis ; that could be from autocomplete or text replacement or something. In fact, it would be helpful if you also showed the code of the entire View.

Thanks very much for your reply. I have created an extract project to just create the issues and raise the questions I have. I have placed it on GitHub and added you to it. The issues I currently face are:

  1. The limitations of the ‘complexity’ in the List
  2. I have found a ‘template’ function on the web which I was hoping to reduce the complexity with. It reminds me of C++ templates, but I couldn’t find the word ‘template’ within the Swift documentation. I added it at the bottom of the UnitsView struct. The call to it to add a 4th picker is currently commented out but it gives an error I don’t understand. The other alternative as you suggested is to create a separate View which displays a single Picker. I tried to do that too but also struggled to transfer the required variables to that view.
  3. The next issue which I could not work out is how to link the picker list user selection to the indices (ex. altitudeUnitIdx) in the UnitSelections class. I know it must use binding ($) but currently I am just defining placeholder @State indices at the top of the View, so it really is not linked to the UnitSelections class indices. So I am trying to use local @State variables and the update the UnitSelections class properties in the onChange() method of the Picker. But this causes an error at the definition of the View…

Sorry about all these questions! Can you help with a few pointers?

OK, I will take a look.

I am more than willing to learn better ways of doing things. Where can I learn about the UserDefaults and the units in Foundation?

Thanks for your awesome help! I have forked your project and added the TextFields which should be unit-aware.

if you are part of the CWC+ membership then we have a small lesson on UserDefaults over on the iOS Bento (UIKit) portion of the courses. theres also little tidbits of functionalities that might be useful to you there

however, be aware that it is in UIKit so it might be a bit different when implementing in SwiftUI, the core concept should be similar though