SwiftUI: 2 Ways to Group Items in a List

Updated: May 11, 2023 By: Khue Post a comment

This practical, example-based article will walk you through a couple of different ways to group items in a List in SwiftUI (caution: you will see a lot of code).

Using listStyle modifier

TL;DR

You can also use the listStyle modifier on your List to change its appearance. There are two styles that are commonly used for grouping items: .grouped and .insetGrouped. The .grouped style creates a list with rounded corners and separators between sections and items. The .insetGrouped style creates a list with inset margins and separators between items only.

List {
    // sections and items
}
.listStyle(.grouped)

Complete example

Screenshot:

The full code:

//
//  GroupedList.swift
//  Examples
//
//  Created by Sling Academy on 19/04/2023.
//

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let name: String
    let category: String
}

struct GroupedList: View {
    let items = [
        Item(name: "Apple", category: "Fruits"),
        Item(name: "Banana", category: "Fruits"),
        Item(name: "Orange", category: "Fruits"),
        Item(name: "Carrot", category: "Vegetables"),
        Item(name: "Broccoli", category: "Vegetables"),
        Item(name: "Spinach", category: "Vegetables")
    ]
    
    func groupByCategory(_ items: [Item]) -> [(String, [Item])] {
        let grouped = Dictionary(grouping: items, by: { $0.category })
        return grouped.sorted(by: { $0.key < $1.key })
    }
    
    var body: some View {
        List {
            ForEach(groupByCategory(items), id:\.0) { pair in
                Section(header:
                            Text(pair.0)
                            .font(.title2)
                            .foregroundColor(.blue)
                        ) {
                    ForEach(pair.1) { item in
                        Text(item.name)
                    }
                }
            }
        }
        .listStyle(.insetGrouped)
    }
}


struct GroupedList_Previews: PreviewProvider {
    static var previews: some View {
        GroupedList()
    }
}

Using the groupBy() method

TL;DR

The second option is to use the groupBy() method on your data collection to create an array of key-value pairs, where the key is the grouping criterion and the value is an array of items that belong to that group. You can then use a ForEach loop to iterate over the key-value pairs and create a Section for each pair.

List {
    ForEach(groupByCategory(items)) { pair in
        Section(header: Text(pair.key)) {
            ForEach(pair.value) { item in
                Text(item.name)
            }
        }
    }
}

Complete example

Screenshot:

The full code:

//
//  GroupedList.swift
//  Examples
//
//  Created by Sling Academy on 19/04/2023.
//

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let name: String
    let category: String
}

struct GroupedList: View {
    let items = [
        Item(name: "Dog", category: "Animals"),
        Item(name: "Cat", category: "Animals"),
        Item(name: "Computer", category: "Devices"),
        Item(name: "iPhone", category: "Devices"),
        Item(name: "Television", category: "Devices"),
        Item(name: "Car", category: "Vehicles"),
        Item(name: "Truck", category: "Vehicles"),
        Item(name: "Bike", category: "Vehicles"),
        Item(name: "Wagon", category: "Vehicles")
    ]
    
    func groupByCategory(_ items: [Item]) -> [(String, [Item])] {
        let grouped = Dictionary(grouping: items, by: { $0.category })
        return grouped.sorted(by: { $0.key < $1.key })
    }
    
    var body: some View {
        List {
            ForEach(groupByCategory(items), id: \.0) { pair in
                Section(header: Text(pair.0)) {
                    ForEach(pair.1) { item in
                        Text(item.name)
                    }
                }
            }
        }
    }
}


struct GroupedList_Previews: PreviewProvider {
    static var previews: some View {
        GroupedList()
    }
}

That’s it.