Данная тема важна при разработке любого приложения, взаимодействующего с сетью. Здесь грамотное использование возможностей системы может значительно улучшить взаимодействие пользователя с программой.
Кеширование уменьшает количество необходимых обращений к сети, улучшает впечатление от работы с программой во время полного отсутствия интернета или проблем с сетевым соединением.
После загрузки ответа сервера, его копия сохраняется в локальном кеше. В следующий раз при посылке такого же запроса, ответ будет возвращен мгновенно, без обращения к сети.
Для использования
Вы можете управлять настройками кеширования — как на стороне клиента, так и на стороне сервера. Грамотный выбор опций может быть полезен при оптимизации вашего приложения.
На стороне запроса к серверу политика кеширования задается с помощью свойства
Различия между этими вариантами не всегда очевидны и часто приводят к путанице. Не добавляет ясности и тот факт, что
То, что действительно нужно знать о
Поскольку класс
В HTTP для обмена метаинформацией о кодировках, MIME-типах, кешировании итп используются заголовки запросов и ответов сервера.
По умолчанию
С
Помимо
При обработке результата запроса делегат
Если метод
Метод
При работе с
Пример
Многие разработчики изобретают свой велосипед для организации кеширования, так как не знают о возможностях
Таким образом, для оптимальной работы своего приложения всегда инициализируйте
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
есть несколько особенностей:- В
iOS 5 кеширование на диске возможно только при использовании HTTP, но не HTTPS. Эта поддержка реализована только вiOS 6 . - Также есть некоторые нюансы при взаимодействии с серверами, не использующими кеширующие заголовки.
Заключение
Пример
NSURLCache
в очередной раз показывает нам, насколько важно знать возможности системы, с которой работаешь. Многие разработчики изобретают свой велосипед для организации кеширования, так как не знают о возможностях
NSURLCache
, инициализация которого занимает всего 2 строчки кода и делает работу в 100 раз эффективнее. Еще большее число вообще не задумывается о преимуществах сетевого кеширования и не использует его, нагружая свой сервер огромным количеством ненужных запросов. Таким образом, для оптимальной работы своего приложения всегда инициализируйте
NSURLCache
в методе application:didFinishLaunchingWithOptions:
.