> Какой метод UITableView используется для dequeue ячейки (iOS, Swift)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Ozon

Стек: iOS, Swift

> Пример ответа

Короткий ответ

Основной метод - dequeueReusableCell(withIdentifier:for:), который возвращает переиспользуемую ячейку для указанного indexPath. Также существует вариант dequeueReusableCell(withIdentifier:) без indexPath, но он не гарантирует корректный размер ячейки при использовании autolayout. Оба метода объявлены в UITableView и требуют предварительной регистрации класса или nib через register(_:forCellReuseIdentifier:).

Подробное объяснение

Метод dequeueReusableCell(withIdentifier:for:) - это основной API для получения ячейки в cellForRowAt. Он работает через пул переиспользования: если ячейка с указанным identifier уже была создана и ушла за пределы экрана, она возвращается повторно, что экономит память и ресурсы.

Разница между двумя вариантами:

  • dequeueReusableCell(withIdentifier:) - возвращает UITableViewCell?, может вернуть nil, если ячейка не зарегистрирована и не создана в storyboard. Не требует indexPath, но не учитывает размеры, связанные с конкретной позицией.
  • dequeueReusableCell(withIdentifier:for:) - возвращает UITableViewCell (не опционально), всегда создаёт ячейку, если пул пуст, и корректно работает с autolayout и estimated row height. Требует indexPath.

Регистрация ячейки обязательна для второго варианта. Регистрировать можно класс (register(_:forCellReuseIdentifier:)) или nib (register(_:forCellReuseIdentifier:)). Если ячейка определена в storyboard через prototype, регистрация не нужна - identifier задаётся в инспекторе.

Важно: при использовании dequeueReusableCell(withIdentifier:for:) внутри cellForRowAt нельзя вызывать его с indexPath, который не соответствует текущему запросу - это приведёт к исключению.

На практике

В типичном UITableViewDataSource методе cellForRowAt порядок действий такой:

  1. Получить ячейку через dequeueReusableCell(withIdentifier:for:).
  2. Привести её к нужному типу (кастомный класс).
  3. Настроить данные.
  4. Вернуть ячейку.

Если ячейка создаётся программно (без storyboard), необходимо в viewDidLoad зарегистрировать класс. Для ячеек из xib - зарегистрировать nib.

Также стоит помнить, что dequeueReusableCell(withIdentifier:) (без for:) может быть полезен в редких случаях, когда нужно проверить наличие ячейки в пуле без создания новой, но на практике это почти не используется.

Пример кода

SWIFT
// Регистрация класса в viewDidLoad
tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
// Регистрация nib
tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "CustomCell")
// Использование в cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as? CustomCell else {
fatalError("Unable to dequeue CustomCell")
}
cell.configure(with: data[indexPath.row])
return cell
}

Как отвечать на собеседовании

Начните с прямого ответа - назовите dequeueReusableCell(withIdentifier:for:). Затем кратко объясните, зачем нужен механизм переиспользования (производительность, память). Упомяните разницу между двумя вариантами и обязательность регистрации. Если спросят про indexPath - объясните, что он нужен для корректной работы с размерами и autolayout. Хорошо добавить пример из практики: как вы регистрируете ячейки и что делаете в cellForRowAt. Не углубляйтесь в детали реализации пула, если не спрашивают.

Что проверяет интервьюер

Интервьюер проверяет:

  • знание базового API UITableView и принципов переиспользования;
  • понимание разницы между dequeueReusableCell(withIdentifier:) и dequeueReusableCell(withIdentifier:for:);
  • знание обязательной регистрации ячейки;
  • способность объяснить, зачем нужен indexPath в методе dequeue;
  • аккуратность в работе с кастомными ячейками (приведение типа, обработка опциональности).

Для senior-уровня важно также показать понимание влияния на производительность и умение избегать типичных ошибок при работе с пулом ячеек.

Типичные ошибки

  • Использование dequeueReusableCell(withIdentifier:) без регистрации - возвращает nil, падение при force unwrap.
  • Забыли зарегистрировать класс или nib - crash с сообщением "unable to dequeue a cell with identifier".
  • Приведение типа без guard let - падение, если identifier указан неверно.
  • Использование dequeueReusableCell(withIdentifier:for:) с неправильным indexPath - исключение.
  • Создание новой ячейки вручную через CustomCell() вместо dequeue - потеря переиспользования, утечки памяти при скролле.
  • Настройка ячейки без сброса предыдущего состояния - данные из старой ячейки остаются при переиспользовании.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью