OutlineGroup in SwiftUI

OutlineGroup is a view used to display hierarchical data in an expandable and collapsible list format. It’s useful for organizing data with multiple levels, like file systems, categories with subcategories, or other nested structures. OutlineGroup works by expanding each level to reveal its child elements, making it a great choice for displaying tree structures.

Basic Structure of OutlineGroup

To create an OutlineGroup, you need:

  1. A hierarchical data structure (often a custom struct or class).
  2. A way to identify children for each item in the hierarchy.
OutlineGroup(data, children: \.children) { item in
    Text(item.name)
}

  • data: The root data, typically an array representing the top level.
  • children: The key path to the children of each item.
  • content: Defines the view for each item.

Example with a Simple Data Model

Let’s define a simple hierarchical model with a name and children property.

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let name: String
    var children: [Item]? // Optional to allow leaf nodes with no children
}

struct ContentView: View {
    let data: [Item] = [
        Item(name: "Fruit", children: [
            Item(name: "Apple"),
            Item(name: "Banana"),
            Item(name: "Cherry")
        ]),
        Item(name: "Vegetables", children: [
            Item(name: "Carrot"),
            Item(name: "Lettuce")
        ])
    ]
    
    var body: some View {
        OutlineGroup(data, children: \.children) { item in
            Text(item.name)
                .padding(.leading, CGFloat(itemDepth(item: item)) * 10)
        }
    }

    // Helper function to calculate depth for indentation
    func itemDepth(item: Item) -> Int {
        var depth = 0
        var currentItem = item
        while let parent = parentOf(item: currentItem) {
            depth += 1
            currentItem = parent
        }
        return depth
    }
    
    // Function to get the parent of an item (optional implementation depending on use case)
    func parentOf(item: Item) -> Item? {
        // Logic to find the parent, if necessary for custom indentation
        return nil
    }
}

Explanation

  • Data Model: The Item struct is the model for each entry in the outline, with an id, name, and optional children.
  • OutlineGroup: Displays the data hierarchy. Each child item is indented using a padding based on its depth.
  • Depth Calculation: itemDepth(item:) calculates how deep each item is to determine how much it should be indented (optional).

Expanding and Collapsing

OutlineGroup automatically handles expanding and collapsing items based on whether they have children. For example:

  • If an Item has children, it appears as a collapsible row.
  • If it doesn’t have children, it’s a leaf node and appears without expansion.

Adding Icons or Custom Views

To enhance each row in OutlineGroup, you can add icons or any custom views, making it resemble a file explorer with folders and files.

OutlineGroup(data, children: \.children) { item in
    HStack {
        Image(systemName: item.children == nil ? "leaf" : "folder")
        Text(item.name)
    }
}

This modification displays a “folder” icon for items with children and a “leaf” icon for items without children.

Nested Data with More Complex Hierarchies

When dealing with multiple nested levels, OutlineGroup automatically handles expanding the appropriate levels of the hierarchy.

For instance, given this nested data:

let data: [Item] = [
    Item(name: "Animals", children: [
        Item(name: "Mammals", children: [
            Item(name: "Dogs"),
            Item(name: "Cats"),
        ]),
        Item(name: "Birds", children: [
            Item(name: "Parrots"),
            Item(name: "Sparrows")
        ])
    ])
]

Using OutlineGroup(data, children: \.children), each level expands as needed, revealing animals, then categories (e.g., “Mammals”), and specific items like “Dogs” and “Cats.”

OutlineGroup is a powerful SwiftUI component for hierarchical data. It:

  • Automatically handles hierarchical layouts: Expands/collapses based on data structure.
  • Customizable: Supports indentation, icons, and custom views.
  • Ideal for tree structures: File systems, category trees, etc.

Leave a Reply