web-dev-qa-db-fra.com

Est-il possible d'empêcher un NSURLRequest de mettre en cache des données ou d'en supprimer à la suite d'une demande?

Sur iPhone, j'exécute une requête HTTP à l'aide de NSURLRequest pour un bloc de données. Les pics d’allocation d’objets et j’assigne les données en conséquence. Lorsque je termine avec les données, je les libère en conséquence - cependant, les instruments ne montrent aucune donnée libérée!

Ma théorie est que, par défaut, les demandes HTTP sont mises en cache - je ne veux pas que mon application iPhone mette en cache ces données. 

Existe-t-il un moyen d'effacer ce cache après une demande ou d'empêcher que des données soient mises en cache en premier lieu?

J'ai essayé d'utiliser toutes les politiques de cache documentées un peu comme ci-dessous:

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

mais rien ne semble libérer la mémoire!

86
Nick Cartwright

Généralement, il est plus facile de créer une requête comme celle-ci.

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

Puis créez la connexion

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

et implémentez la méthode de connexion: willCacheResponse: sur le délégué. Revenir à zéro devrait le faire.

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

J'ai le même problème dans mon application lorsque j'ai demandé des informations à Twitter. Dans mon cas, je n'avais pas besoin de conserver ces informations d'identification, alors je les efface simplement en utilisant le code suivant:

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

J'espère que ça marche pour quelqu'un :)

12
user186215

Si vous utilisez NSURLConnection, jetez un œil au délégué:

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

Valeur de retour

La réponse mise en cache à stocker dans le cache. Le délégué peut renvoyer cachedResponse sans modification, renvoyer une réponse en cache modifiée ou renvoyer nil si aucune réponse en cache ne doit être stockée pour la connexion.

10
catlan

Si ce n'est pas spécifique à une seule demande (vous voulez désactiver le cache pour toute l'application), une seule option est la meilleure.

        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
Sanjeev Rao

Si vous utilisez NSURLSession, une autre solution pour empêcher l'écriture de la demande et des paramètres dans le Cache.db créé par iOS dans le répertoire Caches de l'application consiste à définir la variable NSURLCache pour la configuration de la session sur une mémoire de taille 0 et un cache de disque de taille 0 par exemple.

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

ou comme mentionné ci-dessus défini au niveau du cache global 

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

Vraisemblablement, c'est le 0 pour la taille de disque qui empêche iOS d'écrire sur le disque, mais si vous avez une stratégie de reloadIgnoringLocalCacheData, la mise en cache de la mémoire ne vous intéressera probablement pas non plus. 

Note Ceci empêchera la création de tout dossier Caches/Cache.db (demandes et réponses) ou Caches/fsCachedData/ (données de réponse). Nous avons décidé d'adopter cette approche dans une application à des fins de sécurité, car nous ne voulons plus que nos demandes soient stockées dans le cache du disque.

Si quelqu'un sait s'il existe un moyen d'arrêter uniquement la mise en cache des demandes mais de conserver la mise en cache des données de réponse à partir du mécanisme de chargement d'URL iOS, cela m'intéresserait. (il n'y a pas d'API ou de documentation officielle à ce sujet d'après ce que je peux dire) 

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

En supposant que le serveur soit correctement implémenté, l'insertion de l'en-tête Cache-Control:no-store dans la demande génèrera une réponse du serveur avec le même en-tête, de sorte que NSURLCache ne stockera pas les données de réponse sur le disque. 

Par conséquent, nul besoin de l’approche simpliste consistant à désactiver la mise en cache du disque NSURLCache.

PS: l'ajout de l'en-tête devrait fonctionner pour tous les frameworks HTTP, comme AFNetworking

0
Yuri Brigance