Какие основные причины лагов таблицы (UITableView/UICollectionView) при скролле и как их устранить?

«Какие основные причины лагов таблицы (UITableView/UICollectionView) при скролле и как их устранить?» — вопрос из категории UIKit, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Лаги при скролле обычно вызваны блокировкой главного потока. Основные причины и решения:

1. Неэффективное переиспользование ячеек Убедитесь в правильной регистрации и dequeue ячеек:

tableView.register(CustomCell.self, forCellReuseIdentifier: "CellID")
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath)

2. Тяжелые операции на главном потоке

  • Загрузка изображений: Используйте асинхронную загрузку с кэшированием (NSCache, Kingfisher, SDWebImage)
  • Вычисления: Выносите в фоновые очереди
    DispatchQueue.global(qos: .userInitiated).async {
    let processedData = heavyCalculation()
    DispatchQueue.main.async {
        cell.configure(with: processedData)
    }
    }

3. Сложная авто-верстка (Auto Layout)

  • Рассчитывайте высоту ячеек заранее в heightForRowAt
  • Используйте estimatedRowHeight для оптимизации
  • Кэшируйте рассчитанные размеры

4. Избыточное количество subviews и слоев

  • Упрощайте иерархию view в ячейке
  • Используйте drawRect: для сложной отрисовки вместо множества subviews
  • Избегайте прозрачности (alpha, clearsContextBeforeDrawing)

5. Неоптимизированные графические эффекты

  • Для теней используйте shadowPath
  • Включайте shouldRasterize для статичных сложных слоев
  • Избегайте cornerRadius + masksToBounds на больших view

6. Проблемы в делегатах скролла Не выполняйте тяжелые операции в scrollViewDidScroll:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // ЛЕГКИЕ операции здесь
    // Тяжелые операции — в scrollViewDidEndDecelerating
}

Инструменты для диагностики:

  • Instruments: Time Profiler, Core Animation
  • Debug: Color Offscreen-Rendered, Color Blended Layers
  • Метрики: FPS (CADisplayLink), время рендеринга ячейки