Можно ли запретить NSURLRequest кэшировать данные или удалить кешированные данные после запроса?

90

На iPhone я выполняю HTTP-запрос, используя NSURLRequest для фрагмента данных. Пики распределения объектов, и я соответствующим образом назначаю данные. Когда я заканчиваю с данными, я освобождаю их соответственно - однако инструменты не показывают никаких данных, которые были освобождены!

Моя теория заключается в том, что по умолчанию HTTP-запросы кешируются, однако я не хочу, чтобы мое приложение для iPhone кэшировало эти данные.

Есть ли способ очистить этот кеш после запроса или вообще предотвратить кеширование каких-либо данных?

Я пробовал использовать все политики кеширования, описанные ниже:

NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

но вроде ничего не освобождает память!

Ник Картрайт
источник
Возможно ли, что это не связано с кешем? Вы пытались проверить данные, чтобы увидеть, действительно ли данные, которые следовало перезагрузить, являются старыми? Может быть, ваш лук-порей откуда-то родом. Как инициализировать и освободить NSURLRequests? Это может помочь диагностировать проблему.
lpfavreau 01
К вашему сведению - если вы хотите удалить файлы с помощью грубой силы, вот пример кода для этого: salesforce.stackexchange.com/a/69736
zekel 01

Ответы:

158

Обычно такой запрос проще создать

NSURLRequest *request = [NSURLRequest requestWithURL:url
      cachePolicy:NSURLRequestReloadIgnoringCacheData
      timeoutInterval:60.0];

Затем создайте соединение

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
       delegate:self];

и реализуйте метод connection: willCacheResponse: для делегата. Просто возврат nil должен сделать это.

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
  return nil;
}
tcurdt
источник
Большое спасибо за вашу помощь! Ник.
Ник Картрайт
1
Спасибо за эту идею - я неоднократно вызывал такую ​​веб-службу SOAP, и она бесконтрольно увеличивала кучу, хотя утечки не показали, что что-то не так. Я проводил оптимизацию в течение нескольких дней и, наконец, попытался предотвратить кеширование, поскольку множество объектов CFURL * из внутренней структуры зависало. Единственное, что сработало, - это возврат nil из willCacheResponse!
Брон Дэвис,
15
Почему это нужно делать как NSURLRequestReloadIgnoringCacheData и осуществить connection:willCacheResponse:?
fabb 01
1
Привет, могу ли я использовать это для загрузки локального контента? Вышеупомянутое относится к NSUrlConnection, но я загружаю локальные данные HTML в UIWebView с помощью NSUrlRequest. Мне нужно отказаться от кеширования, поскольку в веб-просмотр из SQLite поступают изображения, а объем памяти увеличивается с каждой загрузкой страницы. Благодарю.
Джим
7
@fabb, переопределение connection:willCacheResponse:позволяет не сохранять ответ в кеше. NSURLRequestReloadIgnoringCacheDataуказывает, что соединение должно загружать запрос без проверки кеша. По-видимому, первое помогает управлять распределением памяти.
Кристофер Пикслей,
12

У меня такая же проблема в приложении, когда я запрашивал информацию в твиттере. В моем случае мне не нужно было сохранять эти учетные данные, поэтому я просто стираю их, используя следующий код:

- (void) eraseCredentials{
NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
NSDictionary *allCredentials = [credentialsStorage allCredentials];

//iterate through all credentials to find the twitter host
for (NSURLProtectionSpace *protectionSpace in allCredentials)
    if ([[protectionSpace host] isEqualToString:@"twitter.com"]){
        //to get the twitter's credentials
        NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
        //iterate through twitter's credentials, and erase them all
        for (NSString *credentialKey in credentials)
            [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    }
}

Надеюсь, у кого-то это сработает :)


источник
это было идеальное решение моей проблемы, у меня была проблема с повторным входом, так как учетные данные хранились и автоматически отправлялись NSURLConnection, большое спасибо, это мне очень помогло :)
RVN
Спасибо, это работа для меня, я очень ценю ваше предложение. На самом деле моя проблема в том, что NSURLRequest хранит имя пользователя и пароль. Так что это поможет удалить учетные данные пользователя из кеша ...
Нилеш Кикани
10

Если вы используете NSURLConnection, посмотрите на делегата:

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse

Возвращаемое значение

Фактический кешированный ответ для сохранения в кеше. Делегат может возвращать cachedResponse без изменений, возвращать измененный кешированный ответ или возвращать nil, если кэшированный ответ не должен храниться для соединения.

Катлан
источник
Большое спасибо здесь. Объем памяти моего приложения внезапно сократился вдвое! Ник.
Ник Картрайт
9

Если вы используете NSURLSession, другое решение для предотвращения записи запросов и параметров в Cache.dbiOS, создаваемых в Cachesкаталоге приложения , состоит в том, чтобы установить NSURLCacheдля конфигурации сеанса память размера 0 и кеш диска размера 0, например

let configuration = URLSessionConfiguration.default    
configuration.urlCache = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)
let session = URLSession(configuration: configuration)

или, как упоминалось выше, установить на уровне глобального кеша

URLCache.shared = URLCache(memoryCapacity: 0, diskCapacity: 0, diskPath: nil)

Предположительно, это 0 для размера диска, который останавливает запись iOS на диск, но если у вас есть политика, reloadIgnoringLocalCacheDataто вы, вероятно, также не заинтересованы в кэшировании памяти.

Примечание. Это предотвратит создание каких-либо Caches/Cache.db(запросы и ответы) или Caches/fsCachedData/папки (данные ответов). Мы решили применить этот подход в приложении в целях безопасности, поскольку мы не хотим, чтобы наши запросы когда-либо хранились в кеше диска.

Если кто-нибудь знает, есть ли способ остановить только кеширование запросов, но сохранить кеширование данных ответа из механизма загрузки URL-адресов iOS, мне было бы интересно узнать. (насколько я могу судить, об этом нет API или официальной документации)

Шагун Мадхикарми
источник
7

Если не относится к одному запросу (вы хотите отключить кеш для всего приложения), то лучшим вариантом будет один ниже. Добавьте этот код в делегат приложения или в зависимости от того, где вам нужно

        int cacheSizeMemory = 0*4*1024*1024; // 0MB
        int cacheSizeDisk = 0*32*1024*1024; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];
Санджив Рао
источник
7
У меня отлично работает, но вы можете просто использовать 0 вместо умножения, которое в любом случае просто заканчивается на 0.
Gary Riches
1
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

Предполагая, что сервер реализован правильно, размещение Cache-Control:no-storeзаголовка в запросе вызовет ответ сервера с тем же заголовком, что приведет NSURLCacheк тому, что данные ответа не будут сохранены на диске.

Следовательно, нет необходимости в дробном подходе к отключению NSURLCacheкеширования диска.

PS: добавление заголовка должно работать для всех фреймворков HTTP, например AFNetworking

Юрий Бриганс
источник