È possibile impedire a una NSURLRequest di memorizzare nella cache i dati o rimuovere i dati memorizzati nella cache a seguito di una richiesta?


89

Su iPhone, eseguo una richiesta HTTP utilizzando NSURLRequest per un blocco di dati. Picchi di allocazione degli oggetti e io assegno i dati di conseguenza. Quando finisco con i dati, li liberi di conseguenza, tuttavia gli strumenti non mostrano che i dati sono stati liberati!

La mia teoria è che per impostazione predefinita le richieste HTTP vengono memorizzate nella cache, tuttavia, non voglio che la mia app per iPhone memorizzi questi dati nella cache.

C'è un modo per svuotare questa cache dopo una richiesta o impedire che i dati vengano memorizzati nella cache in primo luogo?

Ho provato a utilizzare tutti i criteri di cache documentati un po 'come di seguito:

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

ma niente sembra liberare la memoria!


Sarebbe possibile che non sia correlato alla cache? Hai provato a ispezionare i dati per vedere se i dati che avrebbero dovuto essere ricaricati sono in realtà quelli vecchi? Forse il tuo porro viene da altrove. Come si inizializzano e liberano le richieste NSURL? Potrebbe essere di aiuto per diagnosticare il problema.
lpfavreau

FYI - Se vuoi rimuovere i file con la forza bruta, c'è un codice di esempio per farlo qui: salesforce.stackexchange.com/a/69736
zekel

Risposte:


157

Di solito è più facile creare la richiesta in questo modo

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

Quindi crea la connessione

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

e implementare la connessione: willCacheResponse: metodo sul delegato. Basta restituire zero dovrebbe farlo.

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

Grazie mille qui per il tuo aiuto! Nick.
Nick Cartwright

1
Grazie per l'idea: stavo chiamando ripetutamente un servizio web SOAP come questo e aumentava l'heap in modo incontrollabile anche se le perdite non mostravano che qualcosa non andava. Ho ottimizzato per giorni e alla fine ho cercato di impedire la memorizzazione nella cache poiché molti oggetti CFURL * dal framework interno erano in giro. Il ritorno a zero da willCacheResponse è stata l'unica cosa che ha funzionato!
Bron Davies,

15
Perché è necessario fare entrambe le cose NSURLRequestReloadIgnoringCacheData e implementare connection:willCacheResponse:?
fabb

1
Ciao, è possibile che io possa usarlo per caricare contenuti locali? Quanto sopra è per NSUrlConnection ma sto caricando i dati HTML locali in UIWebView utilizzando NSUrlRequest. Devo rifiutare qualsiasi memorizzazione nella cache poiché ci sono immagini che entrano nella visualizzazione Web da SQLite e la memoria aumenta ad ogni caricamento della pagina. Grazie.
jim

7
@fabb, l'override connection:willCacheResponse:consente di non memorizzare la risposta nella cache. NSURLRequestReloadIgnoringCacheDataspecifica che la connessione deve caricare la richiesta senza controllare la cache. Il primo è presumibilmente ciò che aiuta a gestire l'allocazione della memoria.
Christopher Pickslay

12

Ho lo stesso problema nella mia app quando ho richiesto informazioni da Twitter. Nel mio caso non avevo bisogno di conservare quelle credenziali, quindi le cancello semplicemente usando il codice successivo:

- (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];
    }
}

Spero che funzioni per qualcuno :)


questa è stata una soluzione perfetta per il mio problema, ho avuto problemi di ricollegamento, poiché le credenziali sono state memorizzate e sono state inviate automaticamente dalla connessione NSURL, grazie mille mi ha aiutato molto :)
RVN

Grazie, è lavoro per me, ho davvero apprezzato il tuo suggerimento. In realtà il mio problema è che NSURLRequest memorizza nome utente e password. Quindi questo aiuta a rimuovere le credenziali dell'utente dalla cache ...
Nilesh Kikani

10

Se usi NSURLConnection, dai un'occhiata al delegato:

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

Valore di ritorno

La risposta effettiva memorizzata nella cache da archiviare nella cache. Il delegato può restituire cachedResponse senza modifiche, restituire una risposta memorizzata nella cache modificata o restituire nil se nessuna risposta memorizzata nella cache deve essere archiviata per la connessione.


Grazie mille qui. L'impronta di memoria della mia app si è improvvisamente dimezzata! Nick.
Nick Cartwright

9

Se stai utilizzando NSURLSession, un'altra soluzione per impedire che la richiesta e i parametri vengano scritti su Cache.dbiOS crea all'interno della Cachesdirectory dell'app , è impostare la NSURLCacheconfigurazione della sessione su una memoria di dimensione 0 e una cache del disco di dimensione 0, ad es.

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

o, come accennato in precedenza, impostato a livello di cache globale

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

Presumibilmente è lo 0 per la dimensione del disco che interrompe la scrittura di iOS sul disco, ma se hai una politica per reloadIgnoringLocalCacheDataallora probabilmente non sei interessato nemmeno alla cache di memoria.

Nota Ciò impedirà la creazione di Caches/Cache.db(richieste e risposte) o Caches/fsCachedData/cartelle (dati di risposta). Abbiamo deciso di adottare questo approccio in un'app per motivi di sicurezza poiché non vogliamo che le nostre richieste vengano mai archiviate nella cache del disco.

Se qualcuno sa che esiste un modo per interrompere solo la memorizzazione nella cache delle richieste ma mantenere la memorizzazione nella cache dei dati di risposta dal meccanismo di caricamento dell'URL di iOS, sarei interessato a saperlo. (non ci sono API o documentazione ufficiale su questo da quello che posso dire)


7

Se non è specifico per una singola richiesta (U vuoi disabilitare la cache per l'intera app) sotto uno è l'opzione migliore Aggiungi questo codice nel delegato dell'app o in base alle tue necessità

        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
Funziona alla grande per me, ma puoi semplicemente usare 0 invece di fare la moltiplicazione che finisce comunque a 0.
Gary Riches

1
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] url];
[request setValue:@"no-store" forHTTPHeaderField:@"Cache-Control"];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

Supponendo che il server sia implementato correttamente, inserire l' Cache-Control:no-storeintestazione nella richiesta genererà una risposta del server con la stessa intestazione, causando così la NSURLCachemancata memorizzazione dei dati di risposta su disco.

Pertanto, non è necessario l'approccio shotgun di disabilitare la NSURLCachecache del disco.

PS: l'aggiunta dell'intestazione dovrebbe funzionare per tutti i framework HTTP, come AFNetworking

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.