List — що це, компонент списку в SwiftUI

Автор: IT Sectr Опубліковано: 2026-06-25 Час читання: 7 хв

List — це контейнерне View у SwiftUI для відображення даних у вигляді вертикально прокручуваного списку, аналог UITableView в UIKit. Згідно з Apple Developer Documentation, 2024, List підтримує статичні та динамічні секції, свайп-дії, перетягування рядків і pull-to-refresh. На відміну від UITableView, List використовує декларативний API на основі SwiftUI та ForEach, автоматично керуючи перевикористанням комірок і продуктивністю при великій кількості рядків.

Головне

  • List — контейнер для прокручуваного списку даних у SwiftUI
  • ForEach — основний спосіб динамічного відображення даних у List
  • Секції — Section View для групування рядків із заголовками
  • Свайп-дії — swipeActions для iOS 15+
  • Pull-to-refresh — .refreshable для iOS 15+

Що таке List у SwiftUI?

List — це View, що відображає послідовність елементів у вертикально прокручуваному списку. Воно з'явилося в iOS 13 разом зі SwiftUI і є основним способом відображення списків даних, замінюючи UITableView з UIKit. List автоматично керує перевикористанням комірок, скролом і продуктивністю.

List використовує lazy-loading: комірки створюються в міру прокручування, а не всі одразу. Це відрізняє його від VStack із ForEach всередині ScrollView, де всі комірки створюються під час рендерингу. List також надає вбудовану підтримку свайп-дій, pull-to-refresh, редагування (видалити/перемістити) та вибору рядків.

Згідно з Apple WWDC 2021 (Session 10072), List в iOS 15+ отримав суттєві покращення продуктивності завдяки новому механізму diffing на рівні колекцій. Це зробило List більш ефективним при оновленні даних, особливо для списків із сотнями рядків.

List vs ScrollView + VStack

Розробники часто обирають між List і ScrollView з VStack для відображення набору View. Ключова відмінність: List використовує перевикористання комірок (як UITableView), а ScrollView + VStack створює всі View одразу. Для списків із фіксованою кількістю елементів (до 20) різниця незначна. Для динамічних списків із 50+ рядками List є кращим вибором з точки зору продуктивності.

Статичні та динамічні списки

Статичний List — це список із фіксованою кількістю рядків, заданих безпосередньо в тілі List. Використовується для меню, налаштувань і форм із відомим набором елементів. Кожен рядок оголошується явно, без циклів або ForEach.

swift
// Статичний список (для меню та налаштувань)
List {
    Text("Профіль")
    Text("Налаштування")
    Text("Про нас")
}

// Динамічний список (для даних)
struct UserList: View {
    let users: [User]

    var body: some View {
        List(users) { user in
            HStack {
                Text(user.name)
                Text(user.role)
                    .foregroundColor(.secondary)
            }
        }
    }
}

Динамічний List використовує ініціалізатор List(data:rowContent:) або ForEvaluate всередині тіла List. Перший варіант зручний, коли кожен рядок відповідає одному елементу даних. Другий — коли є секції або додаткові елементи між даними.

Ідентифікація (Identifiable): Для динамічних списків елементи даних повинні відповідати протоколу Identifiable або в кортежі data:id потрібно вказати KeyPath до унікального ідентифікатора. SwiftUI використовує ідентифікатори для відстеження змін: додавання, видалення та переміщення рядків.

Секції та групування даних

Section — це View для групування рядків у List із заголовком та опціональним footer. Section приймає header і footer як ViewBuilder, дозволяючи використовувати не лише текст, а й кастомні View для заголовків секцій.

swift
struct SettingsView: View {
    var body: some View {
        List {
            Section(header: Text("Акаунт")) {
                Text("Ім'я")
                Text("Електронна пошта")
            }
            Section(header: Text("Сповіщення")) {
                Toggle("Push", isOn: $pushEnabled)
                Toggle("Email", isOn: $emailEnabled)
            }
        }
        .listStyle(.insetGrouped)
    }
}

// Динамічні секції з ForEach
List {
    ForEach(groupedData.keys.sorted(), id: \.self) { key in
        Section(header: Text(key)) {
            ForEach(groupedData[key]!) { item in
                Text(item.title)
            }
        }
    }
}

Стилі List: SwiftUI надає кілька вбудованих стилів через модифікатор .listStyle(). .insetGrouped — стандартний для iOS Settings, .plain — мінімалістичний, .inset — з відступами, .sidebar — для Sidebar на iPad.

Згідно з SwiftUI Cookbook (2024), Section з динамічними секціями та ForEach всередині — стандартний патерн для групування даних у додатках зі складною структурою. Ключове правило: не вкладайте Section всередину Section і не використовуйте ініціалізатор List(data:) разом із Section — використовуйте ForEach всередині тіла List.

Свайп-дії та pull-to-refresh

.swipeActions(edge:allowsFullSwipe:content:) — модифікатор для iOS 15+, що додає свайп-дії до рядків List. Дозволяє відображати кнопки при свайпі вліво (за замовчуванням) або вправо, з різними кольорами та ролями (destructive, cancel).

swift
struct TaskList: View {
    @Binding var tasks: [Task]

    var body: some View {
        List {
            ForEach($tasks) { $task in
                Text(task.title)
                    .swipeActions(edge: .trailing) {
                        Button("Видалити", role: .destructive) {
                            tasks.removeAll { $0.id == task.id }
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button(task.isDone ? "Скасувати" : "Готово") {
                            task.isDone.toggle()
                        }
                        .tint(.green)
                    }
            }
        }
        .refreshable {
            // Асинхронне завантаження даних
            await loadTasks()
        }
    }
}

.refreshable — модифікатор для iOS 15+, що додає pull-to-refresh. Приймає асинхронне замикання (async), яке виконується, коли користувач тягне список униз. SwiftUI автоматично відображає індикатор завантаження. Після завершення операції індикатор ховається.

.onDelete та .onMove — модифікатори для iOS 13+, що додають підтримку видалення та перестановки рядків. Для їх використання оберніть дані в ForEach із Binding або передайте замикання через .onDelete(perform:) на List або ForEach.

Продуктивність List та оптимізація

Продуктивність List залежить від кількості рядків, складності кожної комірки та частоти оновлень даних. SwiftUI використовує lazy-loading і перевикористання комірок (аналогічно UITableView.dequeueReusableCell), але додаткові оптимізації можуть знадобитися для списків із 500+ рядками.

ОптимізаціяОписВерсія iOS
IdentifiableУнікальні ID для кожного елементаiOS 13+
EquatableViewЗапобігає перемальовуванню при однакових данихiOS 13+
id(_:)Примусове перестворення View при зміні IDiOS 13+
.equatable()Порівняння строго за EquatableiOS 15+
Diffable dataАвтоматичний diff при змінахiOS 15+

Проблема 1: часті оновлення. Якщо дані в списку оновлюються часто (наприклад, кожну секунду), List може перемальовувати видимі комірки при кожній зміні стану. Рішення: використовуйте структури (value types) для даних — SwiftUI порівнює їх за значенням і перемальовує лише змінені рядки.

Проблема 2: важкі комірки. Якщо кожен рядок містить складну ієрархію View, зображення та анімації, скрол може гальмувати. Рішення: виносьте комірки в окремі View, використовуйте EquatableView для запобігання зайвим перемальовуванням. Згідно з SwiftUI Lab (2024), розбиття складного рядка на підкомпоненти знижує час рендерингу на 30–50%.

Проблема 3: велика кількість рядків. При 1000+ рядках List все ще працює ефективно завдяки lazy-loading, але початкове завантаження може сповільнитися через обчислення layout. Рішення: використовуйте LazyVStack лише для списків з однотипними рядками, де не потрібні функції List (свайпи, секції). Для повнофункціональних списків List залишається найкращим вибором.

Часті запитання

Що таке List у SwiftUI?

List — контейнерне View для відображення прокручуваного списку даних у SwiftUI. Аналог UITableView у UIKit з декларативним API. Підтримує секції, свайп-дії, pull-to-refresh, редагування та кастомізацію через .listStyle().

Чим List відрізняється від ScrollView + VStack?

List використовує lazy-loading і перевикористання комірок — комірки створюються в міру прокручування. ScrollView + VStack створює всі View одразу. Для списків із 50+ рядками List кращий. Для фіксованих невеликих наборів (до 20 елементів) різниця незначна.

Як додати pull-to-refresh у List?

Використовуйте модифікатор .refreshable (iOS 15+). Передайте асинхронне замикання з логікою оновлення даних. SwiftUI автоматично відображає індикатор завантаження та ховає його після завершення асинхронної операції.

Як згрупувати рядки в List?

Використовуйте Section View із заголовком та опціональним footer. Всередині Section розміщуйте рядки списку. Для динамічних секцій використовуйте ForEach із groupedData. Стиль списку налаштовується через .listStyle(.insetGrouped) для iOS-подібного вигляду.

Як прискорити List з великою кількістю рядків?

Використовуйте структури (value types) для даних, виносьте складні комірки в окремі View з EquatableView, уникайте частих оновлень стану в кожному рядку. Для списків із 1000+ рядками розгляньте LazyVStack, якщо не потрібні функції List.

Підсумки

  • List — контейнер для прокручуваного списку з lazy-loading і перевикористанням комірок
  • ForEach — основний спосіб динамічного відображення даних у List
  • Section — групування рядків із заголовками та footer
  • swipeActions — свайп-дії для iOS 15+
  • refreshable — pull-to-refresh для iOS 15+
  • Стилі — insetGrouped, plain, inset, sidebar через .listStyle()
  • Продуктивність — використовуйте Identifiable, EquatableView та value types

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також