Как реализовать плейсхолдер для аватарки с разными изображениями для разных клиентов с минимальными изменениями
Что проверяют
Умеете ли вы спроектировать точку расширения так, чтобы новый клиент (white-label сборка или отдельный бренд) добавлялся без правок в экранах. Интервьюеру важно, где живёт знание о клиенте и сколько файлов придётся тронуть. Следом часто спрашивают про переиспользование ячеек и загрузку картинки из сети.
Как отвечать
Начните с уточнения: «клиент» это отдельный таргет приложения или тенант, который определяется в рантайме после логина. От этого зависит решение.
- отдельные таргеты: у каждого свой Asset Catalog с картинкой под одним и тем же именем, например
avatarPlaceholder. Код вообще не меняется,UIImage(named: "avatarPlaceholder")сам достанет нужный вариант из бандла текущей сборки; - рантайм-тенант: протокол
AvatarPlaceholderProvidingс методомplaceholder(for:), реализации под клиентов и одна точка сборки зависимостей. Экран получает провайдер через инициализатор и не знает, какой клиент активен; - генерируемый плейсхолдер: инициалы пользователя на фоне фирменного цвета клиента. Тогда от клиента нужна только палитра, а не набор картинок, и пустых серых кругов в списке нет.
В самом компоненте аватарки последовательность такая: сразу ставим плейсхолдер, запускаем загрузку, по готовности подменяем изображение. В UITableViewCell в prepareForReuse() отменяем предыдущую загрузку и возвращаем плейсхолдер, иначе в ячейке мелькнёт чужое фото. В SwiftUI у AsyncImage есть замыкание placeholder, а Kingfisher и SDWebImage принимают плейсхолдер параметром.
Где спотыкаются
Пишут UIImage(named: "placeholderA")!. Картинку забыли добавить в таргет, и приложение падает при открытии экрана. Нужен фолбэк на общий плейсхолдер или SF Symbol person.crop.circle.
Выбирают клиента строкой через switch прямо во вью. Каждый новый клиент тогда означает правку во всех местах, где показывается аватар, то есть ровно то, чего просили избежать.
Забывают про переиспользование ячеек и асинхронность: картинка от прошлого пользователя приезжает поверх нового, потому что загрузку не отменили и не проверили, что ячейка всё ещё показывает того же человека.