Lista — co to jest, komponent listy w SwiftUI

Autor: IT Sectr Opublikowano: 2026-06-25 Czas czytania: 7 min

List — to kontenerowe View w SwiftUI do wyświetlania danych w formie pionowo przewijanej listy, odpowiednik UITableView w UIKit. Według Apple Developer Documentation, 2024, List obsługuje statyczne i dynamiczne sekcje, akcje przesuwania, przeciąganie wierszy i pull-to-refresh. W przeciwieństwie do UITableView, List używa deklaratywnego API opartego na SwiftUI i ForEach, automatycznie zarządzając ponownym wykorzystaniem komórek i wydajnością przy dużej liczbie wierszy.

Najważniejsze

  • List — kontener do przewijanej listy danych w SwiftUI
  • ForEach — podstawowy sposób dynamicznego wyświetlania danych w List
  • Sekcje — Section View do grupowania wierszy z nagłówkami
  • Akcje przesuwania — swipeActions dla iOS 15+
  • Pull-to-refresh — .refreshable dla iOS 15+

Czym jest List w SwiftUI?

List — to View wyświetlające sekwencję elementów w pionowo przewijanej liście. Pojawiło się w iOS 13 wraz ze SwiftUI i jest podstawowym sposobem wyświetlania list danych, zastępując UITableView z UIKit. List automatycznie zarządza ponownym wykorzystaniem komórek, przewijaniem i wydajnością.

List używa lazy-loading: komórki są tworzone w miarę przewijania, a nie wszystkie naraz. To odróżnia go od VStack z ForEach wewnątrz ScrollView, gdzie wszystkie komórki są tworzone podczas renderowania. List zapewnia również wbudowaną obsługę akcji przesuwania, pull-to-refresh, edycji (delete/move) i zaznaczania wierszy.

Według Apple WWDC 2021 (Session 10072), List w iOS 15+ otrzymał znaczące ulepszenia wydajności dzięki nowemu mechanizmowi diffing na poziomie kolekcji. To sprawiło, że List jest bardziej efektywny przy aktualizacji danych, szczególnie dla list z setkami wierszy.

List vs ScrollView + VStack

Deweloperzy często wybierają między List a ScrollView z VStack do wyświetlania zestawu View. Kluczowa różnica: List używa ponownego wykorzystania komórek (jak UITableView), a ScrollView + VStack tworzy wszystkie View naraz. Dla list ze stałą liczbą elementów (do 20) różnica jest nieznaczna. Dla dynamicznych list z 50+ wierszami List jest preferowany ze względu na wydajność.

Listy statyczne i dynamiczne

Statyczna List — to lista ze stałą liczbą wierszy, określonych bezpośrednio w ciele List. Używana do menu, ustawień i formularzy ze znanym zestawem elementów. Każdy wiersz jest deklarowany jawnie, bez pętli lub ForEach.

swift
// Lista statyczna (dla menu i ustawień)
List {
    Text("Profil")
    Text("Ustawienia")
    Text("O aplikacji")
}

// Lista dynamiczna (dla danych)
struct UserList: View {
    let users: [User]

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

Dynamiczna List używa inicjalizatora List(data:rowContent:) lub ForEach wewnątrz ciała List. Pierwsza opcja jest wygodna, gdy każdy wiersz odpowiada jednemu elementowi danych. Druga — gdy są sekcje lub dodatkowe elementy między danymi.

Identyfikacja (Identifiable): Dla dynamicznych list elementy danych muszą być zgodne z protokołem Identifiable lub w krotce data:id należy podać KeyPath do unikalnego identyfikatora. SwiftUI używa identyfikatorów do śledzenia zmian: dodawania, usuwania i przenoszenia wierszy.

Sekcje i grupowanie danych

Section — to View do grupowania wierszy w List z nagłówkiem i opcjonalnym footer. Section przyjmuje header i footer jako ViewBuilder, pozwalając używać nie tylko tekstu, ale także niestandardowych View dla nagłówków sekcji.

swift
struct SettingsView: View {
    var body: some View {
        List {
            Section(header: Text("Konto")) {
                Text("Nazwa")
                Text("E-mail")
            }
            Section(header: Text("Powiadomienia")) {
                Toggle("Push", isOn: $pushEnabled)
                Toggle("Email", isOn: $emailEnabled)
            }
        }
        .listStyle(.insetGrouped)
    }
}

// Sekcje dynamiczne z ForEach
List {
    ForEach(groupedData.keys.sorted(), id: \.self) { key in
        Section(header: Text(key)) {
            ForEach(groupedData[key]!) { item in
                Text(item.title)
            }
        }
    }
}

Style List: SwiftUI udostępnia kilka wbudowanych stylów poprzez modyfikator .listStyle(). .insetGrouped — standardowy dla iOS Settings, .plain — minimalistyczny, .inset — z wcięciami, .sidebar — dla Sidebar na iPad.

Według SwiftUI Cookbook (2024), Section z dynamicznymi sekcjami i ForEach wewnątrz to standardowy wzorzec do grupowania danych w aplikacjach o złożonej strukturze. Kluczowa zasada: nie zagnieżdżaj Section wewnątrz Section i nie używaj inicjalizatora List(data:) razem z Section — używaj ForEach wewnątrz ciała List.

Akcje przesuwania i pull-to-refresh

.swipeActions(edge:allowsFullSwipe:content:) — modyfikator dla iOS 15+, dodający akcje przesuwania do wierszy List. Pozwala wyświetlać przyciski przy przesunięciu w lewo (domyślnie) lub w prawo, z różnymi kolorami i rolami (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("Usuń", role: .destructive) {
                            tasks.removeAll { $0.id == task.id }
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button(task.isDone ? "Cofnij" : "Gotowe") {
                            task.isDone.toggle()
                        }
                        .tint(.green)
                    }
            }
        }
        .refreshable {
            // Asynchroniczne ładowanie danych
            await loadTasks()
        }
    }
}

.refreshable — modyfikator dla iOS 15+, dodający pull-to-refresh. Przyjmuje asynchroniczne domknięcie (async), które jest wykonywane, gdy użytkownik przeciąga listę w dół. SwiftUI automatycznie wyświetla wskaźnik ładowania. Po zakończeniu operacji wskaźnik jest ukrywany.

.onDelete i .onMove — modyfikatory dla iOS 13+, dodające obsługę usuwania i przenoszenia wierszy. Aby ich użyć, owiń dane w ForEach z Binding lub przekaż domknięcia przez .onDelete(perform:) na List lub ForEach.

Wydajność List i optymalizacja

Wydajność List zależy od liczby wierszy, złożoności każdej komórki i częstotliwości aktualizacji danych. SwiftUI używa lazy-loading i ponownego wykorzystania komórek (analogicznie do UITableView.dequeueReusableCell), ale dodatkowe optymalizacje mogą być potrzebne dla list z 500+ wierszami.

OptymalizacjaOpisWersja iOS
IdentifiableUnikalne ID dla każdego elementuiOS 13+
EquatableViewUnika przerysowania przy równych danychiOS 13+
id(_:)Wymuszone odtworzenie View przy zmianie IDiOS 13+
.equatable()Porównanie ściśle według EquatableiOS 15+
Diffable dataAutomatyczny diff przy zmianachiOS 15+

Problem 1: częste aktualizacje. Jeśli dane na liście są aktualizowane często (np. co sekundę), List może przerysowywać widoczne komórki przy każdej zmianie stanu. Rozwiązanie: używaj struktur (value types) dla danych — SwiftUI porównuje je według wartości i przerysowuje tylko zmienione wiersze.

Problem 2: ciężkie komórki. Jeśli każdy wiersz zawiera złożoną hierarchię View, obrazy i animacje, przewijanie może być wolne. Rozwiązanie: wydzielaj komórki do osobnych View, używaj EquatableView, aby zapobiec zbędnym przerysowaniom. Według SwiftUI Lab (2024), podział złożonego wiersza na podkomponenty zmniejsza czas renderowania o 30–50%.

Problem 3: duża liczba wierszy. Przy 1000+ wierszy List nadal działa wydajnie dzięki lazy-loading, ale początkowe ładowanie może zwolnić z powodu obliczania layoutu. Rozwiązanie: używaj LazyVStack tylko dla list z jednorodnymi wierszami, gdzie nie są potrzebne funkcje List (przesuwanie, sekcje). Dla w pełni funkcjonalnych list List pozostaje najlepszym wyborem.

Często zadawane pytania

Czym jest List w SwiftUI?

List — kontenerowe View do wyświetlania przewijanej listy danych w SwiftUI. Odpowiednik UITableView w UIKit z deklaratywnym API. Obsługuje sekcje, akcje przesuwania, pull-to-refresh, edycję i dostosowywanie przez .listStyle().

Czym List różni się od ScrollView + VStack?

List używa lazy-loading i ponownego wykorzystania komórek — komórki są tworzone w miarę przewijania. ScrollView + VStack tworzy wszystkie View naraz. Dla list z 50+ wierszami List jest preferowany. Dla stałych małych zestawów (do 20 elementów) różnica jest nieznaczna.

Jak dodać pull-to-refresh w List?

Użyj modyfikatora .refreshable (iOS 15+). Przekaż asynchroniczne domknięcie z logiką odświeżania danych. SwiftUI automatycznie wyświetla wskaźnik ładowania i ukrywa go po zakończeniu asynchronicznej operacji.

Jak zgrupować wiersze w List?

Użyj Section View z header i opcjonalnym footer. Wewnątrz Section umieść wiersze listy. Dla dynamicznych sekcji użyj ForEach z groupedData. Styl listy konfiguruje się przez .listStyle(.insetGrouped) dla wyglądu przypominającego iOS.

Jak przyspieszyć List z dużą liczbą wierszy?

Używaj struktur (value types) dla danych, wydzielaj złożone komórki do osobnych View z EquatableView, unikaj częstych aktualizacji stanu w każdym wierszu. Dla list z 1000+ wierszami rozważ LazyVStack, jeśli nie są potrzebne funkcje List.

Podsumowanie

  • List — kontener do przewijanej listy z lazy-loading i ponownym wykorzystaniem komórek
  • ForEach — podstawowy sposób dynamicznego wyświetlania danych w List
  • Section — grupowanie wierszy z nagłówkami i footer
  • swipeActions — akcje przesuwania dla iOS 15+
  • refreshable — pull-to-refresh dla iOS 15+
  • Style — insetGrouped, plain, inset, sidebar przez .listStyle()
  • Wydajność — używaj Identifiable, EquatableView i value types

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również