Понимание того, как использовать ForEach и Идентифицируемые

Список позволяет представлять строки данных, которые организованы в один столбец. Он работает так же, как UITableView из UIKit, который служит наиболее распространенным элементом управления пользовательским интерфейсом в iOS. Его основная цель — представить список данных, которые обычно можно найти в контентном или новостном приложении.

Если у вас уже есть опыт работы с UITableView, вы знаете, как утомительно создавать простую таблицу. И еще сложнее построить с пользовательскими ячейками. Хорошо то, что список SwiftUI может выполнить его всего несколькими строками кода, упростив процесс. Даже пользовательская ячейка требует минимальных усилий в SwifUI.

Это руководство является частью моей серии Руководство по SwiftUI.

Давайте создадим новый проект или откроем существующий, который вы используете для практики. Вы можете использовать эту ссылку, если вам нужен пошаговый процесс, как это сделать.

Основной список

Чтобы понять, как работает список. Сначала начнем создавать простой. В приведенном ниже коде показано, насколько просто работать со списком.

struct ContentView: View {
    
    var body: some View {
            
        List {
            Text("Content 1")
            Text("Content 2")
            Text("Content 3")
            Text("Content 4")
            Text("Content 5")
        }
        
    }
    
}

Использование ForEach

Приведенный выше код работает, если у вас есть несколько содержимого для вставки. Но как насчет того, чтобы разместить сотни или более предметов. Ручной ввод всего не является хорошей практикой программирования. Не говоря уже о количестве времени и энергии, необходимых для ввода огромного количества данных. Вот где использование ForEach делает код в нашем списке эффективным.

В приведенном ниже коде показано, как это сделать с помощью ForEach.

struct ContentView: View {
    
    var body: some View {
            
        List {

            ForEach(1...5, id: \.self) { index in
                Text("Content \(index)")
            }
            
        }
        
    }
    
}

Что даст тот же результат.

Мы можем еще больше упростить код, опустив индекс и используя сокращение $0. Это означает обращение к первому параметру диапазона. Это то же самое, как массив обрабатывает индекс.

Мы еще не закончили, мы все еще можем сделать это лучше, позволив List обрабатывать коллекцию. Вот простейшая форма кода:

struct ContentView: View {
    
    var body: some View {
            
        List (1...5, id: \.self) {
            Text("Content \($0)")
        }
        
    }
    
}

Понимание

Сокращение от идентификатора. Его основная цель состоит в том, чтобы однозначно идентифицировать каждый элемент. Вы оцените его полезность, когда у вас будут сложные коллекции. Например, элементы с текстом и изображением.

Давайте создадим хорошо продуманный список, подобный тому, который вы видите ниже.

Но сначала нам нужны изображения. Не стесняйтесь использовать любое изображение, которое вам нравится. Вы можете скачать с unsplash, если у вас нет доступных фотографий для этой практики.

Кредиты следующим владельцам фотографий из unsplash, которые я использовал в этом уроке: Энни Спратт, Набиль Сайед, Роберт Лукеман, Рёдзи Ивата и XPS.

Убедитесь, что все изображения, которые вы будете использовать, уже находятся в каталоге Assets. Если вы впервые имеете дело с изображениями, эта ссылка дает хорошую основу для работы с изображениями в SwiftUI.

Первое, что нам нужно сделать, это создать специальную структуру, в которой мы можем разместить текст и изображение вместе, тогда каждая пара будет идентифицироваться индивидуально. Напишите этот код ниже ContentView.

struct Collections {
    var name: String
    var image: String
}

Далее мы создаем массив, в котором будут храниться изображения и текст. Напишите этот код внутри ContentView.

var collections = [

    Collections(name: "Cafe", image: "xps"),
    Collections(name: "Home", image: "annie-spratt"),
    Collections(name: "Commute", image: "nabeel-syed"),
    Collections(name: "Travel", image: "robert-lukeman"),
    Collections(name: "Public", image: "ryoji-iwata")
        
]

Важно! Убедитесь, что вы изменили имя изображения на имя файла изображения, которое вы будете использовать. Если вы не знаете, как это сделать, рекомендую сначала пройти этот туториал.

Прежде чем составить список, давайте сначала спроектируем, как будут выглядеть строки. Создайте отдельную структуру под структурой Collections и поместите этот код.

struct ImageLabelRow: View {
    
    var collection: Collections

    var body: some View {
        ZStack(alignment: .leading) {
            Image(collection.image)
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(height: 150)
                .cornerRadius(20)
                .overlay(
                    Rectangle()
                        .foregroundColor(.black)
                        .cornerRadius(20)
                        .opacity(0.4)
                )

            Text(collection.name)
                .font(.system(.largeTitle, design: .rounded))
                .fontWeight(.black)
                .foregroundColor(.white)
                .padding()
        }
    }
    
}

Наконец, давайте создадим список. Введите этот код внутри ContentView.

var body: some View {
            
    List(collections, id: \.name) { index in
            
        ImageLabelRow(collection: index)
            
    }
        
}

Обратите внимание, что мы используем .name в качестве идентификатора в параметре для уникальной идентификации каждой пары. Вы также можете использовать .image, так как struct Collections имеет 2 переменные: имя и изображение.

Таким образом, вся программа должна выглядеть так:

Но ждать. Хотя этот код работает, это не лучшая практика. Например, вы будете использовать то же название «Кафе» или то же изображение. Это вызовет проблемы при создании ссылок для каждой строки.

Отредактируйте структуру Collections и преобразуйте ее в протокол Идентифицируемый. Это означает, что вы говорите ему присваивать себе уникальный идентификатор для каждого созданного экземпляра. Поэтому обновите код следующим образом:

struct Collections: Identifiable {
    var id = UUID()
    var name: String
    var image: String
}

Тогда вам больше не понадобится параметр id, так как каждый элемент уже имеет уникальный идентификатор благодаря протоколу Identifying. Обновите код в списке, как показано ниже.

var body: some View {
            
    List(collections) { index in
            
        ImageLabelRow(collection: index)
            
    }
        
}

Итак, вот как выглядит окончательный исходный код:

Я добавил ссылку на GitHub для всего исходного кода этого проекта:

https://github.com/athurion/SwiftUI-Tutorial-Working-with-List-using-ForEach

В нашем следующем уроке мы разберемся с концепцией состояние и привязка.

Да пребудет с вами код,

-Дуга