Как устроен компонент List в SwiftUI?

Ответ

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

Ключевые механизмы:

  1. Автоматическое управление ячейками: SwiftUI применяет паттерн переиспользования ячеек (как dequeueReusableCell в UIKit) для эффективного использования памяти.
  2. Lazy-загрузка: Элементы рендерятся по мере необходимости при прокрутке, что критично для длинных списков.
  3. Diffable Data Source: При изменении исходных данных (@State, @Observable) SwiftUI автоматически вычисляет разницу (diff) и применяет минимально необходимые обновления к таблице, обеспечивая плавные анимации.

Пример базового использования:

struct ContentView: View {
    @State private var items = ["Item 1", "Item 2", "Item 3"]

    var body: some View {
        List(items, id: .self) { item in
            Text(item)
        }
        .onDelete { indices in
            items.remove(atOffsets: indices)
        } // SwiftUI автоматически анимирует удаление
    }
}

Ограничения и нюансы:

  • Для сложных, нелинейных раскладок (например, сеток) больше подходит LazyVGrid/LazyHGrid.
  • Сильная абстракция может затруднить тонкую настройку внешнего вида или анимации, доступную при прямой работе с UITableView.
  • Производительность List для статических данных или очень простых ячеек часто выше, чем у ScrollView + VStack, благодаря использованию нативных механизмов UIKit.

Ответ 18+ 🔞

А, ну вот, смотри, опять этот ваш «List» в SwiftUI. Ну, блядь, высокоуровневая абстракция, говорит. А под капотом-то что? Правильно, старый добрый UITableView, который там на iOS сидит и потихоньку ебёт мозги всем, кто пытался с ним вручную работать. Ну, слава богу, хоть спрятали его, суку, подальше.

Как эта штука, блядь, работает, если по-человечьи:

  1. Ячейки не плодятся как сумасшедшие. Ты думаешь, на каждый элемент новую ячейку создают? Хуй там! Там всё как у взрослых — паттерн переиспользования. Тупо берут ячейку, которая за экраном уплыла, и пихают в неё новые данные. Как dequeueReusableCell в UIKit, только тебе об этом думать не надо, ёпта. Умно, чо.
  2. Ленивая загрузка, блядь. Не будет он весь список из тысячи элементов сразу в память грузить, пока ты до них не докрутил. Рендерит по мере надобности. Иди-ка, прокрути — получишь. А не прокрутил — и хуй с ним, не тратим ресурсы. Красота.
  3. Автоматические обновления — просто пиздец. Ты там в коде поменял массив items, добавил или удалил что-то. SwiftUI сам, блядь, вычисляет разницу между «было» и «стало» (это и есть Diffable Data Source, если по-умному) и применяет только нужные изменения к таблице. Удалил элемент — он с красивой анимацией нахуй уедет. Тебе даже думать об этом не нужно, волнение ебать — ноль.

Вот, смотри, как это выглядит в коде, проще пареной репы:

struct ContentView: View {
    @State private var items = ["Item 1", "Item 2", "Item 3"]

    var body: some View {
        List(items, id: .self) { item in
            Text(item)
        }
        .onDelete { indices in
            items.remove(atOffsets: indices)
        } // И всё, блядь! Удалится с анимацией, сам всё сделает!
    }
}

Но не всё так гладко, конечно, есть и подводные ебучки:

  • Если тебе нужна не просто список, а, например, сетка или какая-нибудь хитрая раскладка — List не твой вариант. Тут уже надо LazyVGrid или LazyHGrid смотреть, там свои приколы.
  • Абстракция она, блядь, сильная. Хочешь какую-то нестандартную анимацию или тонко настроить вид, как в старом добром UIKit? Можешь и обосраться. Всё спрятано, достучаться сложно.
  • И да, запомни: для простых списков производительность у List часто выше, чем если ты начнёшь городить ScrollView с VStack внутри. Потому что он использует нативные, оптимизированные годами механизмы UITableView. Так что не выёбывайся, используй, где надо.

Вот и вся магия, блядь. Вроде умно сделано, но иногда так и хочется крикнуть: «Да отдайте мне доступ к таблице, я сам всё сделаю!». Но нет, сиди и радуйся, что за тебя половину работы сделали.