Как правильно использовать guard let для создания ячейки в UITableView
Что проверяют
Понимаете ли вы, зачем здесь guard и что делать в ветке else, когда метод обязан вернуть ячейку. Следом спрашивают, чем guard let ... as? с fatalError лучше или хуже простого as!.
Как отвечать
Типичный случай для guard let в cellForRowAt это приведение кастомной ячейки:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ProfileCell.reuseIdentifier, for: indexPath) as? ProfileCell else { fatalError("ProfileCell не зарегистрирована") }
Что стоит проговорить:
guardобязан выйти из области видимости:return,throwили функция с типомNever, напримерfatalError. После негоcellдоступна уже неопциональной до конца метода, без вложенности, как было бы сif let;- почему не
return UITableViewCell(): неудачное приведение это ошибка программиста (зарегистрирован не тот класс, опечатка в идентификаторе). Пустая ячейка молча спрячет баг, а падение с понятным сообщением покажет его на первом запуске. Если падать в релизе недопустимо, берутassertionFailureи запасную ячейку: в отладке упадёт, в продакшене нет; - данные отдельно от ячейки: выход через
guardгодится для программных ошибок. Отсутствующие данные модели (нет аватара, пустое имя) это нормальное состояние, для него ячейка показывает заглушку, а не прерывает метод; - синтаксис: начиная со Swift 5.7 можно писать короче,
guard let user else { ... }вместоguard let user = user.
Хорошо упомянуть дженерик-хелпер: приведение и fatalError прячут в расширение dequeue<T>(for:), и в cellForRowAt остаётся одна строка.
Где спотыкаются
Используют guard let для доступа к массиву: guard let item = items[indexPath.row]. Сабскрипт массива не опционален, за границами он падает, а не возвращает nil, а с неопциональными элементами такой код даже не скомпилируется.
В ветке else возвращают пустую UITableViewCell() и получают пустые строки в таблице, причину которых потом ищут часами.
Путают методы: dequeueReusableCell(withIdentifier:) без indexPath возвращает опционал, и его распаковывают через guard, хотя правильнее взять версию с for: indexPath и зарегистрированную ячейку.