Как происходит запрос данных при изменении аватарки
Что проверяют
Умеете ли вы провести фичу целиком: выбор фото, подготовку, сетевой запрос, обработку ошибок и обновление всех экранов, где видна аватарка. Следом спрашивают, что будет, если пользователь свернёт приложение во время загрузки или пропадёт сеть.
Как отвечать
Разложите на шаги:
- выбор:
PhotosPickerв SwiftUI илиPHPickerViewControllerв UIKit. Пикер работает в отдельном процессе и не требует доступа ко всей медиатеке. Фото может прийти в HEIC и огромного размера; - подготовка: обрезка под квадрат, уменьшение от 500 до 1000 точек по стороне,
jpegData(compressionQuality:). Делать это стоит вне главного потока; - запрос:
multipart/form-dataчерезURLSessionс async APIupload(for:from:), заголовокAuthorization, таймаут. Альтернатива, которую часто выбирает бэкенд: приложение получает presigned URL, кладёт файл прямо в хранилище и подтверждает загрузку отдельным запросом; - ответ: успехом считаете весь диапазон 2xx, из тела берёте новый URL аватарки. 401 уводит в обновление токена, 413 означает, что файл слишком большой;
- UI: оптимистично показываете локальную картинку сразу, при ошибке возвращаете старую и предлагаете повторить.
Отдельно про запрос данных после смены. URL аватарки лучше делать версионным (с хешем или временем обновления), тогда URLCache и библиотеки кэширования картинок подтянут новую, а не покажут старую. Остальные экраны узнают об изменении через общий источник данных: @Observable-модель профиля, Combine-паблишер или notification, а не повторным запросом профиля с каждого экрана.
Если загрузка должна пережить сворачивание, нужна background-сессия URLSession, а она принимает загрузку только из файла, не из Data в памяти.
Где спотыкаются
Выставляют Content-Type дважды, сначала JSON, потом multipart, или теряют boundary. Сервер отвечает 400, и начинается долгая отладка.
Сравнивают статус строго с 200, хотя сервер вправе ответить 201 или 204.
Грузят картинку в исходном размере и держат несколько декодированных UIImage в памяти. Фото на 12 мегапикселей в декодированном виде занимает около 48 МБ.