List — este un View container în SwiftUI pentru afișarea datelor sub forma unei liste derulabile vertical, un analog al UITableView în UIKit. Conform Apple Developer Documentation, 2024, List suportă secțiuni statice și dinamice, acțiuni de glisare, tragerea rândurilor și pull-to-refresh. Spre deosebire de UITableView, List folosește o API declarativă bazată pe SwiftUI și ForEach, gestionând automat reutilizarea celulelor și performanța la un număr mare de rânduri.
Elemente principale
List — este un View care afișează o secvență de elemente într-o listă derulabilă vertical. A apărut în iOS 13 împreună cu SwiftUI și este modalitatea principală de afișare a listelor de date, înlocuind UITableView din UIKit. List gestionează automat reutilizarea celulelor, derularea și performanța.
List utilizează lazy-loading: celulele sunt create pe măsură ce derulați, nu toate odată. Aceasta îl diferențiază de VStack cu ForEach în interiorul ScrollView, unde toate celulele sunt create la randare. List oferă, de asemenea, suport integrat pentru acțiuni de glisare, pull-to-refresh, editare (ștergere/mutare) și selectare a rândurilor.
Conform Apple WWDC 2021 (Session 10072), List în iOS 15+ a primit îmbunătățiri semnificative de performanță datorită unui nou mecanism de diffing la nivel de colecții. Acest lucru a făcut List mai eficient la actualizarea datelor, în special pentru liste cu sute de rânduri.
Dezvoltatorii aleg adesea între List și ScrollView cu VStack pentru afișarea unui set de View-uri. Diferența cheie: List folosește reutilizarea celulelor (ca UITableView), iar ScrollView + VStack creează toate View-urile deodată. Pentru liste cu un număr fix de elemente (până la 20), diferența este nesemnificativă. Pentru liste dinamice cu 50+ rânduri, List este preferată din punct de vedere al performanței.
List statică — este o listă cu un număr fix de rânduri, specificate direct în corpul List. Este utilizată pentru meniuri, setări și formulare cu un set cunoscut de elemente. Fiecare rând este declarat explicit, fără bucle sau ForEach.
// Listă statică (pentru meniuri și setări)
List {
Text("Profil")
Text("Setări")
Text("Despre")
}
// Listă dinamică (pentru date)
struct UserList: View {
let users: [User]
var body: some View {
List(users) { user in
HStack {
Text(user.name)
Text(user.role)
.foregroundColor(.secondary)
}
}
}
}
List dinamică folosește inițializatorul List(data:rowContent:) sau ForEach în interiorul corpului List. Prima opțiune este convenabilă când fiecare rând corespunde unui element de date. A doua — când există secțiuni sau elemente suplimentare între date.
Identificare (Identifiable): Pentru liste dinamice, elementele de date trebuie să se conformeze protocolului Identifiable sau în tuplul data:id trebuie specificat KeyPath către un identificator unic. SwiftUI folosește identificatorii pentru a urmări modificările: adăugarea, ștergerea și mutarea rândurilor.
Section — este un View pentru gruparea rândurilor în List cu titlu și footer opțional. Section acceptă header și footer ca ViewBuilder, permițând utilizarea nu doar a textului, ci și a View-urilor personalizate pentru titlurile secțiunilor.
struct SettingsView: View {
var body: some View {
List {
Section(header: Text("Cont")) {
Text("Nume")
Text("Email")
}
Section(header: Text("Notificări")) {
Toggle("Push", isOn: $pushEnabled)
Toggle("Email", isOn: $emailEnabled)
}
}
.listStyle(.insetGrouped)
}
}
// Secțiuni dinamice cu ForEach
List {
ForEach(groupedData.keys.sorted(), id: \.self) { key in
Section(header: Text(key)) {
ForEach(groupedData[key]!) { item in
Text(item.title)
}
}
}
}
Stiluri List: SwiftUI oferă mai multe stiluri integrate prin modificatorul .listStyle(). .insetGrouped — standard pentru iOS Settings, .plain — minimalist, .inset — cu indentări, .sidebar — pentru Sidebar pe iPad.
Conform SwiftUI Cookbook (2024), Section cu secțiuni dinamice și ForEach în interior este un model standard pentru gruparea datelor în aplicații cu structură complexă. Regula cheie: nu încadrați Section în interiorul Section și nu utilizați inițializatorul List(data:) împreună cu Section — utilizați ForEach în interiorul corpului List.
.swipeActions(edge:allowsFullSwipe:content:) — modificator pentru iOS 15+ care adaugă acțiuni de glisare la rândurile List. Permite afișarea butoanelor la glisarea la stânga (implicit) sau la dreapta, cu diferite culori și roluri (destructive, cancel).
struct TaskList: View {
@Binding var tasks: [Task]
var body: some View {
List {
ForEach($tasks) { $task in
Text(task.title)
.swipeActions(edge: .trailing) {
Button("Șterge", role: .destructive) {
tasks.removeAll { $0.id == task.id }
}
}
.swipeActions(edge: .leading) {
Button(task.isDone ? "Anulează" : "Gata") {
task.isDone.toggle()
}
.tint(.green)
}
}
}
.refreshable {
// Încărcare asincronă a datelor
await loadTasks()
}
}
}
.refreshable — modificator pentru iOS 15+ care adaugă pull-to-refresh. Acceptă o închidere asincronă (async) care se execută când utilizatorul trage lista în jos. SwiftUI afișează automat indicatorul de încărcare. După finalizarea operațiunii, indicatorul este ascuns.
.onDelete și .onMove — modificatori pentru iOS 13+ care adaugă suport pentru ștergerea și mutarea rândurilor. Pentru a le utiliza, încadrați datele în ForEach cu Binding sau transmiteți închideri prin .onDelete(perform:) pe List sau ForEach.
Performanța List depinde de numărul de rânduri, complexitatea fiecărei celule și frecvența actualizărilor de date. SwiftUI utilizează lazy-loading și reutilizarea celulelor (similar cu UITableView.dequeueReusableCell), dar optimizări suplimentare pot fi necesare pentru liste cu 500+ rânduri.
| Optimizare | Descriere | Versiune iOS |
|---|---|---|
| Identifiable | ID unic pentru fiecare element | iOS 13+ |
| EquatableView | Evită re-randarea la date egale | iOS 13+ |
| id(_:) | Recrearea forțată a View la schimbarea ID | iOS 13+ |
| .equatable() | Comparare strictă după Equatable | iOS 15+ |
| Diffable data | Diff automat la modificări | iOS 15+ |
Problema 1: actualizări frecvente. Dacă datele din listă sunt actualizate frecvent (de exemplu, în fiecare secundă), List poate re-randa celulele vizibile la fiecare schimbare de stare. Soluție: utilizați structuri (value types) pentru date — SwiftUI le compară după valoare și re-randează doar rândurile modificate.
Problema 2: celule grele. Dacă fiecare rând conține o ierarhie complexă de View-uri, imagini și animații, derularea poate fi lentă. Soluție: mutați celulele în View-uri separate, utilizați EquatableView pentru a preveni re-randările inutile. Conform SwiftUI Lab (2024), împărțirea unui rând complex în subcomponente reduce timpul de randare cu 30–50%.
Problema 3: număr mare de rânduri. La 1000+ rânduri, List funcționează în continuare eficient datorită lazy-loading, dar încărcarea inițială poate încetini din cauza calculării layout-ului. Soluție: utilizați LazyVStack doar pentru liste cu rânduri omogene, unde nu sunt necesare funcțiile List (glisare, secțiuni). Pentru liste complet funcționale, List rămâne cea mai bună alegere.
Întrebări frecvente
List — un View container pentru afișarea unei liste derulabile de date în SwiftUI. Analogul UITableView în UIKit cu API declarativă. Suportă secțiuni, acțiuni de glisare, pull-to-refresh, editare și personalizare prin .listStyle().
List utilizează lazy-loading și reutilizarea celulelor — celulele sunt create pe măsură ce derulați. ScrollView + VStack creează toate View-urile deodată. Pentru liste cu 50+ rânduri, List este preferată. Pentru seturi fixe mici (până la 20 de elemente), diferența este nesemnificativă.
Utilizați modificatorul .refreshable (iOS 15+). Transmiteți o închidere asincronă cu logica de actualizare a datelor. SwiftUI afișează automat indicatorul de încărcare și îl ascunde după finalizarea operațiunii asincrone.
Utilizați Section View cu header și footer opțional. Plasați rândurile listei în interiorul Section. Pentru secțiuni dinamice, utilizați ForEach cu groupedData. Stilul listei se configurează prin .listStyle(.insetGrouped) pentru un aspect asemănător iOS.
Utilizați structuri (value types) pentru date, mutați celulele complexe în View-uri separate cu EquatableView, evitați actualizările frecvente de stare în fiecare rând. Pentru liste cu 1000+ rânduri, luați în considerare LazyVStack dacă nu sunt necesare funcțiile List.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și