Home > OS >  SwiftUI ordered list from dictionery
SwiftUI ordered list from dictionery

Time:10-19

I'm trying to make an ordered list like this:

  1. Lorem ipsum dolor sit amet
    • consectetur adipiscing elit
    • sed do eiusmod tempor
  2. Nemo enim ipsam voluptatem quia
    • voluptatem sequi nesciunt.
    • ad minima veniam

So i try to use ForEach with [String: [String]],

but compiler gives me an error "Failed to produce diagnostic for expression; please submit a bug report "

What it the proper way to loop over this array of values ?

    struct SelectDeviceInfoView: View {
    let data: [String: [String]] = [
        "1. Check your iOS device settings" : ["Ensure that your iOS device is connected to the same Wifi network as your TV.", "Any “Safe browsing” plugins/apps or VPN proxies on your iOS device will block the detection of TVs. You should disable them.", "Check your phone Wifi settings. Go to 'Settings' > 'Wi-Fi' > Select the connected network (click the blue ⓘ button) > Ensure “Private Address” is turned off.", "Ensure that the app has permission to access devices in your local network. Go to 'Settings' > 'Privacy' > 'Local Network' > Ensure “Screen Mirror” app has the permission."],
        "2. Check your router settings" : ["If you're using a multi-band router (e.g. with 2.4 and 5 GHz antennas). So both your TV and iOS device should be on the same band.", "Ensure that you aren’t connected to the public Wifi network; such networks only provide an internet connection, but block all all other internal network traffic. So you can’t connect to a Smart TV.", "Verify that UPNP is enabled in your Router settings.", "Check whether you have multiple subnets in your network. In that case you won’t be able to connect to TV.", "Reboot the router to renew the IP address of your TV.", "Unplug the power cord, wait 1 minute and reconnect the power cord. Also do this for other network devices, such as Wifi repeaters and etc.", "If you have a router with MAC address filtering, add the MAC address of your TV to the list of filtered devices.", "Disable Access Point/Client isolation on your router.", "Disable Wireless Isolation on your router."]]
    
    
    var body: some View { <-- error here
        VStack {
            List {
                ForEach(data.sorted(using: >), id: \.key) { key, value in
                    Section(header: Text(key)) {
                        ForEach(value, id: \.self) { text in
                            Text(text)
                        }
                    }
                }
            }
        }
    }
}

CodePudding user response:

Data for the ForEach should be a RandomAccessCollection. But Dictionary is not.

One of the possible data structure for this use case is the Array ( conformed to RandomAccessCollection ). So that we have to create custom data array.

struct MyData: Hashable { // <=here
    let title: String
    let sortedSubItems: [String]
}

struct ContentView: View {
    let data: [String: [String]] = [
        "1. Check your iOS device settings" : ["Ensure that your iOS device is connected to the same Wifi network as your TV.", "Any “Safe browsing” plugins/apps or VPN proxies on your iOS device will block the detection of TVs. You should disable them.", "Check your phone Wifi settings. Go to 'Settings' > 'Wi-Fi' > Select the connected network (click the blue ⓘ button) > Ensure “Private Address” is turned off.", "Ensure that the app has permission to access devices in your local network. Go to 'Settings' > 'Privacy' > 'Local Network' > Ensure “Screen Mirror” app has the permission."],
        "2. Check your router settings" : ["If you're using a multi-band router (e.g. with 2.4 and 5 GHz antennas). So both your TV and iOS device should be on the same band.", "Ensure that you aren’t connected to the public Wifi network; such networks only provide an internet connection, but block all all other internal network traffic. So you can’t connect to a Smart TV.", "Verify that UPNP is enabled in your Router settings.", "Check whether you have multiple subnets in your network. In that case you won’t be able to connect to TV.", "Reboot the router to renew the IP address of your TV.", "Unplug the power cord, wait 1 minute and reconnect the power cord. Also do this for other network devices, such as Wifi repeaters and etc.", "If you have a router with MAC address filtering, add the MAC address of your TV to the list of filtered devices.", "Disable Access Point/Client isolation on your router.", "Disable Wireless Isolation on your router."]]
    
    var listData: [MyData] { // <=here
        data.map {
            MyData(title: $0.key, sortedSubItems: $0.value.sorted(by: { $0 < $1 }))
        }
        .sorted { $0.title < $1.title }
    }
    
    var body: some View {
        VStack {
            List {
                ForEach(listData , id: \.self) {  myDataItem in
                    Section(header: Text(myDataItem.title)) {
                        ForEach(myDataItem.sortedSubItems, id: \.self) { sortedSubItem in
                            Text(sortedSubItem)
                        }
                    }
                }
            }
        }
    }
}
  • Related