Pull to refresh

MemCache для iOS

Reading time2 min
Views1.3K
Предистория появления класса MemCache тривиальна. Есть в разработке проект который большую часть времени занимается подгрузкой небольших объемов данных из сети. В основном JSON данные и небольшие изображения. В каждом контроллере был объявлен NSMutableDictionary в котором и сохранялись результаты запросов. Но с ростом количества контроллеров возникло две проблемы — дублирование кода и потеря результатов кеширования при вызове popViewController.

Под катом решение этих проблем.

Было решено провести рефакторинг по проекту в результате которого родился класс-синглтон 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.
Tags:
Hubs:
Total votes 24: ↑22 and ↓2+20
Comments11

Articles