Как устроена система идентификаторов ячеек в iOS
Что проверяют
Понимаете ли вы механизм переиспользования ячеек, а не только умеете вызвать dequeue. Следом обычно спрашивают, почему при быстром скролле в ячейке появляется чужая картинка и что меняет современный API с регистрациями.
Как отвечать
Reuse identifier это имя вида ячейки, а не конкретной ячейки. Таблица держит очередь переиспользования на каждый идентификатор: ячейка, ушедшая с экрана, попадает в очередь, и следующий dequeue с тем же идентификатором вернёт её вместо создания новой. Поэтому на список из десяти тысяч строк создаётся примерно столько ячеек, сколько видно на экране, плюс несколько про запас.
Ключевые детали:
- регистрация:
register(_:forCellReuseIdentifier:)с классом илиUINib. Прототип в сториборде регистрируется сам, идентификатор задаётся в Interface Builder; dequeueReusableCell(withIdentifier:for:): всегда возвращает ячейку, а на незарегистрированном идентификаторе падает. Старый вариант безfor:возвращает опционал иnil, если очередь пуста;prepareForReuse(): вызывается перед повторной выдачей. Здесь отменяют загрузку картинки и сбрасывают выделение, а контент целиком выставляют вcellForRowAt;- разные виды: на каждый класс ячейки свой идентификатор, иначе придёт ячейка не того класса и приведение типа упадёт;
- современный путь: с iOS 14 есть
UICollectionView.CellRegistrationиdequeueConfiguredReusableCell(using:for:item:), строковый идентификатор уходит из кода. Не путайте его с идентификаторами элементов вUICollectionViewDiffableDataSource: те описывают данные и должны бытьHashable.
Где спотыкаются
Говорят, что у каждой ячейки должен быть уникальный идентификатор. Тогда переиспользования нет вовсе, и память растёт вместе со списком.
Грузят картинку асинхронно и по завершении кладут в ячейку, не проверив, что она всё ещё показывает ту же строку. Итог: чужие аватарки при скролле. Нужна отмена в prepareForReuse() или сверка идентификатора модели.
Заполняют ячейку частично: у одной строки подзаголовок есть, у другой нет, и если его не сбросить, переиспользованная ячейка покажет старый текст.