Чи можна запобігти запиту NSURLRequest у кешування даних або видалити кешовані дані після запиту?


89

На iPhone я виконую запит HTTP, використовуючи NSURLRequest для частини даних. Піки розподілу об’єктів, і я відповідно присвоюю дані. Коли я закінчую з даними, я звільняю їх відповідно - однак прилади не показують жодних даних, які були звільнені!

Моя теорія полягає в тому, що за замовчуванням HTTP-запити кешуються, однак - я не хочу, щоб мій додаток iPhone кешував ці дані.

Чи є спосіб очистити цей кеш після запиту або запобігти спочатку кешуванню будь-яких даних?

Я спробував використовувати всі політики кешування, задокументовані трохи, як показано нижче:

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

але, здається, ніщо не звільняє пам’ять!


Чи можливо, що це не пов’язано з кешем? Ви пробували перевіряти дані, щоб перевірити, чи дані, які слід було перезавантажити, насправді є старими? Можливо, ваш цибуля-порей приходить звідкись. Як ініціалізувати та звільнити запити NSURLRequests? Це може допомогти діагностувати проблему.
lpfavreau

FYI - Якщо ви хочете видалити файли грубою силою, є приклад коду для цього тут: salesforce.stackexchange.com/a/69736
zekel

Відповіді:


157

Зазвичай простіше створити такий запит

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

Потім створіть з'єднання

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

і реалізуйте метод делегату зв’язку: willCacheResponse:. Просто повернення нуля повинно це зробити.

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
  return nil;
}

Велике спасибі за допомогу! Нік.
Нік Картрайт

1
Дякую за цю ідею - я неодноразово телефонував до веб-сервісу SOAP, і він неконтрольовано нарощував купу, навіть незважаючи на те, що витоки не показували, що щось не так. Я оптимізував кілька днів і нарешті спробував запобігти кешуванню, оскільки багато об’єктів CFURL * з внутрішнього фреймворку зависали. Повернення nil з willCacheResponse було єдиним, що спрацювало!
Брон Девіс,

15
Чому це потрібно робити як NSURLRequestReloadIgnoringCacheData і здійснити connection:willCacheResponse:?
fabb

1
Привіт, чи можливо я можу використовувати це для завантаження локального вмісту? Вище для NSUrlConnection, але я завантажую локальні дані HTML у UIWebView за допомогою NSUrlRequest. Мені потрібно відхилити будь-яке кешування, оскільки зображення переходять у веб-перегляд від SQLite, а пам'ять збільшується з кожним завантаженням сторінки. Дякую.
jim

7
@fabb, перевизначення connection:willCacheResponse:дозволяє не зберігати відповідь у кеші. NSURLRequestReloadIgnoringCacheDataвказує, що з'єднання повинно завантажувати запит без перевірки кешу. Перший, мабуть, допомагає керувати розподілом пам'яті.
Крістофер Піклай,

12

У мене така сама проблема в моєму додатку, коли я запитував інформацію у Twitter. У моєму випадку мені не потрібно було зберігати ці облікові дані, тому я просто стираю їх, використовуючи наступний код:

- (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 немодифікованим, повернути модифіковану кешовану відповідь або повернути нуль, якщо для з'єднання не слід зберігати кешовану відповідь.


Дуже дякую тут. Слід пам'яті мого додатка раптово зменшився вдвічі! Нік.
Нік Картрайт

9

Якщо ви використовуєте NSURLSession, іншим рішенням для запобігання запису запитів та параметрів, що Cache.dbстворюються в iOS, не створюється в 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.