Ответ
UITableView — компонент для отображения одно- или многосекционных вертикальных списков.
UICollectionView — гибкий компонент для отображения данных в произвольных макетах.
Сравнительный анализ:
| Характеристика | UITableView | UICollectionView |
|---|---|---|
| Макет по умолчанию | Вертикальный список, 1 колонка | Сетка (flow layout) или кастомный |
| Ориентация | Только вертикальная | Любая (через scrollDirection) |
| Ячейки | UITableViewCell со стандартными стилями |
UICollectionViewCell полностью кастомные |
| Заголовки/подвалы | tableHeaderView, tableFooterView, секционные |
Supplementary views через UICollectionReusableView |
| Делегат | UITableViewDelegate |
UICollectionViewDelegate |
| Источник данных | UITableViewDataSource |
UICollectionViewDataSource |
| Анимации | Встроенные для строк | Кастомные через UICollectionViewLayout |
| Переиспользование | dequeueReusableCell(withIdentifier:) |
dequeueReusableCell(withReuseIdentifier:for:) |
Пример UITableView:
class SimpleListVC: UIViewController, UITableViewDataSource {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "Row (indexPath.row)"
return cell
}
}
Пример UICollectionView с кастомным макетом:
class GridVC: UIViewController, UICollectionViewDataSource {
let layout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 5
layout.scrollDirection = .vertical
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
return layout
}()
lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.configure(with: indexPath)
return cell
}
}
Рекомендации по выбору:
-
Используйте UITableView для:
- Простых списков (настройки, меню)
- Мастер-деталь интерфейсов
- Когда нужны стандартные стили ячеек (
.subtitle,.value1)
-
Используйте UICollectionView для:
- Сеток фотографий
- Горизонтальных каруселей
- Кастомных макетов (Pinterest-style, staggered grid)
- Анимированных переходов между layout
- Когда нужны сложные supplementary views
Производительность:
- Оба компонента эффективно переиспользуют ячейки
UICollectionViewможет быть медленнее при сложных layout вычислениях- Для больших наборов данных используйте prefetching (
UITableViewDataSourcePrefetching,UICollectionViewDataSourcePrefetching)
Ответ 18+ 🔞
А, вот это я люблю, про наши родные скроллящиеся штуки! Сидишь такой, думаешь — ну что мне взять, чтобы список нарисовать? А тут, блядь, два монстра на выбор: один старый, проверенный, как дедовский москвич, а второй — как новенькая иномарка, в которую можно всё воткнуть, что в голову взбредёт.
Так, смотри. Есть у нас UITableView — это, можно сказать, классика жанра, столп и опора. Он умеет делать одно: вертикальный список, одна колонка, всё ровно, как под линеечку. Как будто бы твоя бабушка перечисляет, что купить в магазине на бумажке. Просто, понятно, без выебонов.
А есть UICollectionView — это уже, сука, полный разгул фантазии. Хочешь — сетку фоток сделай, хочешь — горизонтальную карусель, хочешь — разбросай ячейки по экрану в стиле «пьяный дизайнер». Это как конструктор «Лего» против простых кубиков.
Краткая сводка, чтобы не еб@ть мозг:
| Критерий | UITableView | UICollectionView |
|---|---|---|
| Как выглядит | Вертикальный список, один столбец | Да что угодно! Сетка, карусель, абстракция. |
| Крутить можно? | Только сверху вниз | Куда захочешь, хоть по диагонали (шучу, но почти). |
| Ячейки | Есть готовые стили (с подзаголовком, с картинкой) | Делай сам с нуля, как художник. |
| Шапки и подвалы | Есть простые для всей таблицы и для секций | Есть, но через supplementary views — чуть сложнее. |
| Кто управляет? | UITableViewDelegate и UITableViewDataSource |
UICollectionViewDelegate и UICollectionViewDataSource (логично, да?) |
| Анимации | Встроенные для добавления/удаления строк | Мощные, через кастомные лейауты — можно творить магию. |
| Как ячейки берем? | dequeueReusableCell(withIdentifier:) |
dequeueReusableCell(withReuseIdentifier:for:) (чуть длиннее, блядь). |
Вот тебе пример UITableView, проще пареной репы:
class SimpleListVC: UIViewController, UITableViewDataSource {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "Row (indexPath.row)"
return cell
}
}
Видишь? Зарегистрировал, написал два метода — и готово, список торчит. Никакой ебли.
А вот UICollectionView уже посерьёзнее, с кастомной сеткой:
class GridVC: UIViewController, UICollectionViewDataSource {
let layout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 5
layout.scrollDirection = .vertical
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
return layout
}()
lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CustomCell
cell.configure(with: indexPath)
return cell
}
}
Тут уже нужно лейаут настраивать — размеры ячеек, отступы, направление скролла. Но зато и возможности — овердохуища!
Так что когда что брать?
Тащи UITableView, если:
- Делаешь простой список настроек, типа «Звук», «Уведомления», «О приложении».
- Нужен стандартный мастер-деталь интерфейс (список контактов -> детали контакта).
- Лень заморачиваться — нужны готовые стили ячеек (
.subtitle,.value1). Работает из коробки, ёпта!
Врубай UICollectionView, если:
- Делаешь галерею или сетку фоток (как в Instagram).
- Нужна горизонтальная карусель товаров или баннеров.
- Хочется выебистый макет в стиле Pinterest, где ячейки разной высоты.
- Планируешь анимированные переходы между разными раскладками.
- Нужны сложные дополнительные view (шапки, подвалы, фоны для секций), которые не влезают в простые рамки.
По производительности:
Оба, блядь, молодцы — ячейки переиспользуют, как заправские скряги. Но UICollectionView может начать подтупливать, если у тебя лейаут с хуёвиной логикой расчётов на каждую ячейку. Для огромных списков в обоих случаях юзай prefetching (UITableViewDataSourcePrefetching или UICollectionViewDataSourcePrefetching), чтобы подгружать данные заранее и не ждать, пока пользователь доскроллит и пошлёт тебя нахуй из-за лагов.
Короче, выбор за тобой. Хочешь просто и надёжно — бери таблицу. Хочешь, чтобы всё летало и сверкало, и было не как у всех — коллекшн. Главное — не пытайся коллекшном сделать простой список, это как молотком гвоздь забивать, который и так пальцем вдавливается.