NSCache - встроенный в
Foundation механизм для кэширования данных в памяти. В отличие от обычного словаря,
NSCache сам очищается при нехватке памяти, потокобезопасен и не вызывает циклов сильных ссылок. Для задач вроде кэширования картинок, разобранного текста или результатов парсинга это отличный выбор.
В чем подвох:
NSCache пришел из
Objective-C, поэтому и ключи, и значения должны быть ссылочными типами (AnyObject).
String и
Int так просто не положить - нужно оборачивать в
NSString или
NSNumber. На практике это неудобно, но решается оберткой.
Как сделать удобную обертку:
Можно написать generic-класс
Cache, который внутри хранит
NSCache.
WrappedKey - класс-обертка для ключа,
Entry - для значения. Благодаря этому можно будет работать с обычными типами (String, Int и другими структурами).
Важные ограничения:
На проде почти всегда нужно задавать
countLimit и
totalCostLimit. Иначе кэш может незаметно разрастись и занять всю память.
totalCostLimit - примерная граница суммарного размера объектов.
cost при вставке - абстрактная метрика. Для изображений можно использовать
width * height, для текста -
count (length). Главное, чтобы более объемные объекты удалялись из кэша в первую очередь.
Когда NSCache подходит:
- Кэширование изображений в таблицах и коллекциях.
- Результаты разбора Markdown в NSAttributedString.
- Тяжелые вычисления (фильтры, предикты).
- Результаты парсинга, которые не критично потерять.
Когда не подходит:
- Данные, которые должны переживать перезапуск приложения (здесь нужно сохранять в память).
- Кэш с TTL (временем жизни).
- Сетевые ответы с управлением через заголовки (для этого есть URLCache).
Что еще важно:
NSCache сам реагирует на нехватку памяти и чистится без вашего участия. Ручная очистка по уведомлению о памяти не нужна и даже вредна - вы удалите то, что система, возможно, еще могла бы оставить.
Потокобезопасность
NSCache гарантирована для отдельных операций. Но если у вас логика из нескольких шагов (проверил -> вычислил -> сохранил), синхронизацию нужно делать самостоятельно.
Вывод:
NSCache - отличный базовый инструмент для некритичного кэширования в памяти. Он не требует сложных настроек, не боится проблем с памятью и хорошо вписывается в архитектуру, где отсутствие данных в кэше - это просто небольшая задержка, а не ошибка. Но важно помнить про его ограничения: ключи и значения - только классы, лимиты нужно задавать явно, а для постоянного хранения нужны другие механизмы.