Предистория появления класса MemCache тривиальна. Есть в разработке проект который большую часть времени занимается подгрузкой небольших объемов данных из сети. В основном JSON данные и небольшие изображения. В каждом контроллере был объявлен NSMutableDictionary в котором и сохранялись результаты запросов. Но с ростом количества контроллеров возникло две проблемы — дублирование кода и потеря результатов кеширования при вызове popViewController.
Под катом решение этих проблем.
Было решено провести рефакторинг по проекту в результате которого родился класс-синглтон MemCache и две категории, по одной для NSString и NSObject.
Класс MemCache должен был выполнять кэширование на небольшое время (в этом проекте было достаточно двух минут), самостоятельно очищать память при возникновении MemoryWarning, а также при переходе приложения в фон.
Ссылка на исходники в конце статьи, а пока расскажу про основные этапы реализации.
В методе init подписываемся на уведомления о memory warnings и потере активности.
Не забываем отписаться от уведомлений в dealloc.
Так как кэш может быть очищен в любой момент времени по запросу или по наступлении описанных выше событий, при записи нового элемента нужно проверять, а есть ли собственно куда писать. Для каждого элемента при добавлении запускаем отложенный вызов метода удаления его из кэша.
Для удобства использования использовал категории. Теперь чтобы положить объект в кэш, достаточно написать что-то вроде:
А достать объект можно так:
Ссылка на репозиторий — github.com/eltiren/MemCahce-IOS
P.S. Компилировал с включенным ARC.
Под катом решение этих проблем.
Было решено провести рефакторинг по проекту в результате которого родился класс-синглтон MemCache и две категории, по одной для NSString и NSObject.
Класс MemCache должен был выполнять кэширование на небольшое время (в этом проекте было достаточно двух минут), самостоятельно очищать память при возникновении MemoryWarning, а также при переходе приложения в фон.
Ссылка на исходники в конце статьи, а пока расскажу про основные этапы реализации.
В методе init подписываемся на уведомления о memory warnings и потере активности.
- (id) init
{
self = [super init];
if (self != nil)
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(clearCache)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
[center addObserver:self
selector:@selector(clearCache)
name:UIApplicationWillResignActiveNotification
object:nil];
_lifeTime = 60.0f;
}
return self;
}
Не забываем отписаться от уведомлений в dealloc.
- (void)dealloc
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
[center removeObserver:self
name:UIApplicationWillResignActiveNotification
object:nil];
}
Так как кэш может быть очищен в любой момент времени по запросу или по наступлении описанных выше событий, при записи нового элемента нужно проверять, а есть ли собственно куда писать. Для каждого элемента при добавлении запускаем отложенный вызов метода удаления его из кэша.
- (void)setValue:(id)value forKey:(NSString *)key
{
if (!_cache)
{
_cache = [[NSMutableDictionary alloc] init];
}
[_cache setValue:value forKey:key];
[NSObject cancelPreviousPerformRequestsWithTarget:_cache selector:@selector(removeObjectForKey:) object:key];
[_cache performSelector:@selector(removeObjectForKey:) withObject:key afterDelay:_lifeTime];
}
Для удобства использования использовал категории. Теперь чтобы положить объект в кэш, достаточно написать что-то вроде:
[jsonValue setMemCacheValueForKey:[[[connection originalRequest] URL] absoluteString]];
А достать объект можно так:
id val = [[url absoluteString] memCacheValue];
Ссылка на репозиторий — github.com/eltiren/MemCahce-IOS
P.S. Компилировал с включенным ARC.