How to create SwiftUI List View

A List view in SwiftUI is a container which helps us to display static or dynamic data in a scrollable column. By default we get standard styling of List. Let us create a simple List with static data to illustrate it.

var body: some View {
        List {
            Text("First Item")
            Text("Second Item")
            Text("Third Item")
        }
    }

This simple List with static data will look like

Dynamic List View

We use very little static data list and mostly List is populated with dynamic data fetched either from api or from database. Suppose we want to create a list of students. First we will create a Student struct with properties ‘rollNo’ and ‘name’.

struct Student {
    var rollNo: Int
    var name: String
}

Now we can create an array of students to create a list

let students = [
        Student(rollNo: 1, name: "Alice"),
        Student(rollNo: 2, name: "Bob"),
        Student(rollNo: 3, name: "Charlie")
    ]
    
var body: some View {
     List(students) { student in
            HStack {
                Text("\(student.rollNo)")
                Text(student.name)
            }
        }
    }

After writing this piece of code you will get an error that Student should conform to Identifiable protocol.

In order to fix this error we can use rollNo as identifier after conforming to protocol Identifiable. Now the Student struct code will be

struct Student : Identifiable {
    var id: Int {rollNo}
    var rollNo: Int
    var name: String
}

The error will go away once we make the Student conforming to protocol Identifiable

Custom Cell in ListView

Creating a custom cell in SwiftUI is very simple. Which helps us to build complex and interactive user interfaces. Suppose we want to show image as well with student’s name. We have to add image property in our Student struct.

struct Student : Identifiable {
    var id: Int {rollNo}
    var rollNo: Int
    var name: String
    var image: String
}

For simplicity I will provide the system ‘person’ image to each student instance and will ignore the roll no in custom cell.

let students = [
        Student(rollNo: 1, name: "Alice", image: "person"),
        Student(rollNo: 2, name: "Bob", image: "person"),
        Student(rollNo: 3, name: "Charlie", image: "person")
    ]
    
    
    var body: some View {
        List(students) { student in
            HStack {
                Image(systemName: student.image)
                                .resizable()
                                .frame(width: 30, height: 30)
                                
                Text(student.name)
            }
        }
    }

We can create more complex UI as per requirement. It is easy and straightforward compared to the custom cell of a tableview in UIKit.

Sections in ListView

ListView can be divided into multiple sections. Each section can have a header and a footer. Let me create two arrays of students to demonstrate the sections concept.

let students = [
        Student(rollNo: 1, name: "Alice"),
        Student(rollNo: 2, name: "Bob"),
        Student(rollNo: 3, name: "Charlie")
    ]
    
    let students2 = [
        Student(rollNo: 4, name: "Charlie"),
        Student(rollNo: 5, name: "David"),
        Student(rollNo: 6, name: "Eve"),
    ]

I will use two ‘Section’ views with headers ‘CLASS A’ and ‘CLASS B’ respectively. Inside the section view I am using ‘ForEach’ view to iterate over the students array for both sections.

var body: some View {
        List {
            Section {
                ForEach(students){student in
                    HStack {
                        Text("\(student.rollNo)")
                        Text(student.name)
                    }
                }
            } header: {
                Text("Class A")
                    .foregroundStyle(.red)
            }
            Section {
                ForEach(students2){student in
                    HStack {
                        Text("\(student.rollNo)")
                        Text(student.name)
                    }
                }
            } header: {
                Text("Class B")
                    .foregroundStyle(.red)
            }
            
        }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *