Как реализовать репозиторий для одного экрана, чтобы не запрашивать все данные с сервера каждый раз
Что проверяют
Понимаете ли вы, что кеш это прежде всего политика: откуда брать данные, когда считать их устаревшими и кто их сбрасывает. Следом спрашивают, что будет, если экран запросит данные дважды одновременно, и где хранить кеш, чтобы он пережил перезапуск.
Как отвечать
Репозиторий прячет от экрана источники данных и отдаёт один метод вроде func items() async throws -> [Item] или поток значений. Внутри несколько слоёв:
- память: словарь или
NSCacheна время жизни сессии, самый быстрый слой; - диск: SwiftData, Core Data или JSON-файл в
Caches, если данные нужны сразу после запуска и офлайн; - HTTP:
URLCacheи заголовкиETagиCache-Control. На ответ304 Not Modifiedтело не качается заново, эту бесплатную экономию часто упускают; - сеть: источник свежих данных.
Политику назовите явно. Stale-while-revalidate: сразу отдаёте закешированное, в фоне запрашиваете свежее и обновляете экран, для этого удобен AsyncStream или CurrentValueSubject в Combine. К этому TTL, свой для ленты и для справочников, и принудительное обновление по pull-to-refresh. Если API умеет, запрашивайте только изменения с метки updatedAt, а не весь список.
Потокобезопасность: сделайте репозиторий actor. Одновременные вызовы склеивайте: храните текущий Task загрузки и отдавайте его всем, кто пришёл, пока он не завершился. Два обращения дадут один сетевой запрос.
После изменений (удаление, редактирование) обновляйте кеш локально, не дожидаясь полной перезагрузки, иначе экран покажет старое состояние.
Где спотыкаются
Кешируют без инвалидации. Данные однажды загрузились и живут до перезапуска приложения, пользователь видит удалённые записи и не понимает почему.
Хранят кеш в обычном свойстве класса и пишут в него из completion-обработчика на фоновом потоке. Это гонка данных, и строгая проверка конкурентности Swift 6 такой код не пропустит.
Делают репозиторий синглтоном с данными пользователя и не чистят его при выходе из аккаунта. Следующий пользователь на том же устройстве увидит чужой список.