Данная тема значима при разработке всякого приложения, взаимодействующего с сетью. Тут грамотное применение вероятностей системы может гораздо усовершенствовать взаимодействие пользователя с программой.
NSURLCache
— это комплексное решение для кеширования сетевых запросов в оперативной памяти либо на диске. В соответствии с документацией Apple, всякий запрос с применением NSURLConnection
будет «пропущен» через NSURLCache
.
Кеширование сокращает число нужных обращений к сети, улучшает ощущение от работы с программой во время полного отсутствия интернета либо задач с сетевым соединением.
Позже загрузки результата сервера, его копия сохраняется в локальном кеше. В дальнейший раз при посылке такого же запроса, результат будет возвращен мигом, без обращения к сети. NSURLCache
прозрачным для пользователя образом вернет закешированные данные.
Для применения NSURLCache
необходимо установить значение синглтона sharedURLCache
. Это дозволено сделать в способе application:didFinishLaunchingWithOptions:
на iOS либо вapplicationDidFinishLaunching:
— на Mac OS X:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024
diskCapacity:20 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:URLCache];
}
Вы можете руководить настройками кеширования — как на стороне заказчика, так и на стороне сервера. Грамотный выбор опций может быть пригоден при оптимизации вашего приложения.
NSURLRequestCachePolicy
На стороне запроса к серверу политика кеширования задается с поддержкой свойства cachePolicy
объектаNSURLRequest
. Допустим выбор одного из следующих вариантов:
NSURLRequestUseProtocolCachePolicy
— значение по умолчанию. Логика кеширования определяется реализацией сетевого протокола, используемого в запросе.
NSURLRequestReloadIgnoringLocalCacheData
— данные неизменно грузятся с сервера, содержимое кеша всецело игнорируется.
NSURLRequestReloadIgnoringLocalAndRemoteCacheData
— содержимое локального кеша игнорируется. Помимо этого, прокси-сервера и иная промежуточная инфраструктура должна быть проинструктирована не применять по вероятности закешированную копию данных.
NSURLRequestReturnCacheDataElseLoad
— информация возвращается из кеша, при этом данные о ее актуальности не учитываются. Если данные в кеше отсутствуют — они грузятся из сети.
NSURLRequestReturnCacheDataDontLoad
— данные берутся из кеша, данные об их устаревании игнорируются. Впрочем, если сохраненная информация отсутствует — запрос сразу считается не прошедшим, без попытки получить ее с сервера.
NSURLRequestReloadRevalidatingCacheData
— закешированные данные применяются только позже заблаговременного подтверждения их валидности сервером. Ставшие неактуальными данные — выкачиваются из сети.
Отличия между этими вариантами не неизменно очевидны и Зачастую приводят к путанице. Не добавляет ясности и тот факт, что NSURLRequestReloadIgnoringLocalAndRemoteCacheData
иNSURLRequestReloadRevalidatingCacheData
— в тезисе не реализованы.
То, что подлинно необходимо знать о NSURLRequestCachePolicy
дозволено резюмировать дальнейшим образом:
UseProtocolCachePolicy
— поведение по умолчанию
ReloadIgnoringLocalCacheData
— не применять кеш
ReloadIgnoringLocalAndRemoteCacheData
— не применять кеш. Вовсе
ReturnCacheDataElseLoad
— применять кеш. Игнорировать информацию о его актуальности
ReturnCacheDataDontLoad
— оффлайн-режим. Применять только закешированные данные, самостоятельно от их «свежести»
ReloadRevalidatingCacheData
— перед применением спросить у сервера, насколько кеш актуален
Кеширование в HTTP
От того что класс NSURLConnection
предуготовлен для работы с разными сетевыми протоколами (включая FTP и HTTP/HTTPS) в документации кеширование описано протоколо-самостоятельным образом. В данной статье мы будем рассматривать его с точки зрения протокола HTTP.
В HTTP для обмена метаинформацией о кодировках, MIME-типах, кешировании итп применяются заголовкизапросов и результатов сервера.
Заголовки запроса
По умолчанию NSURLRequest
использует нынешнее время для того, Дабы определить, необходимо ли возвращать закешированную информацию. Для больше тонкой настройки дозволено применять следующие заголовки:
If-Modified-Since
— данный заголовок соответствует заголовку Last-Modified
результата от сервера. Его значение необходимо установить в Last-Modified
из последнего обращения к данному сервису.
If-None-Match
— соответствует Etag
-заголовку результата. Сюда необходимо передать предыдущее полученное значение Etag
.
Заголовки результата
С NSHTTPURLResponse
также могут быть возвращены заголовки, относящиеся к кешированию:
Cache-Control
— данный заголовок должен присутствовать в результате, Дабы включить HTTP-кеширование на заказчике. Его значение может содержать информацию о продолжительности хранения данных в кеше, а также об ярусе доступа к ним. Подробная информация доступна тут.
Помимо Cache-Control
, сервер может прислать добавочные заголовки, применяющиеся для условного приобретения данных (см. предыдущую секцию):
Last-Modified
— время последнего метаморфозы запрашиваемого источника. Скажем при приобретении информации о фотоальбоме заголовок Last-Modified
может быть установлен в значение, равнозначное дате последнего фото.
Etag
— идентификатор содержимого требуемого объекта. На практике это может быть, скажем, MD5-хэшсостояния источника. Это благотворно в случае динамически генерирующихся данных, для которых определение Last-Modified
проблематично.
NSURLConnectionDelegate
При обработке итога запроса делегат NSURLConnection
имеет вероятность изменить закешированный результат с поддержкой способа connection:willCacheResponse:
. В данный вызов передается объектNSCachedURLResponse
, тот, что содержит ссылку на начальный NSURLResponse
и закешированные данные в виде NSData
. Данный объект создается на основе информации, полученной из сетевого соединения. От того что вы не можете изменять экземпляры класса NSCachedURLResponse
, для редактирования каких-либо параметров необходимо сделать новейший объект с поддержкой инициализатораinitWithResponse:data:userInfo:storagePolicy:
, скажем:
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
NSMutableDictionary *mutableUserInfo = [[cachedResponse userInfo] mutableCopy];
NSMutableData *mutableData = [[cachedResponse data] mutableCopy];
NSURLCacheStoragePolicy storagePolicy = NSURLCacheStorageAllowedInMemoryOnly;
// ...
return [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response]
data:mutableData
userInfo:mutableUserInfo
storagePolicy:storagePolicy];
}
Если способ connection:willCacheResponse:
вернет nil
— результат не будет закеширован вообще.
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
return nil;
}
Способ connection:willCacheResponse:
— опциональный. Если он не реализован в делегате, будет использован механически сделанный экземпляр NSCachedURLResponse
.
Подводные камни
При работе с NSURLCache
есть несколько особенностей:
Завершение
Пример NSURLCache
в следующий раз показывает нам, насколько значимо знать вероятности системы, с которой трудишься.
Многие разработчики изобретают свой велосипед для организации кеширования, так как не знают о вероятностях NSURLCache
, инициализация которого занимает каждого 2 строчки кода и делает работу в 100 раз результативнее. Еще большее число вообще не задумывается о превосходствах сетевого кеширования и не использует его, нагружая свой сервер громадным числом непотребных запросов.
Таким образом, для оптимальной работы своего приложения неизменно инициализируйте NSURLCache
в способе application:didFinishLaunchingWithOptions:
.