Est-il possible d'empêcher un NSURLRequest de mettre en cache des données ou de supprimer des données en cache suite à une requête?
-
03-07-2019 - |
Question
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 requête ou d'empêcher la mise en cache de données en premier lieu?
J'ai essayé d'utiliser toutes les stratégies de cache décrites un peu comme ci-dessous:
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
theRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
mais rien ne semble libérer la mémoire!
La solution
Généralement, il est plus facile de créer une requête comme ceci
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0];
Créez ensuite la connexion
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request
delegate:self];
et implémentez la méthode de connexion: willCacheResponse: sur le délégué. Il suffit de renvoyer zéro pour le faire.
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
return nil;
}
Autres conseils
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 cela fonctionnera pour quelqu'un:)
Si vous utilisez NSURLConnection, examinez le délégué:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
Valeur renvoyée
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.
S'il n'est pas spécifique à une requête unique (vous voulez désactiver le cache de l'application entière), une des options ci-dessous est la meilleure. Ajoutez ce code dans le délégué de l'application ou en fonction de vos besoins
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];
Si vous utilisez NSURLSession
, une autre solution pour empêcher l'écriture de la requête et des paramètres sur Cache.db
crée dans Caches
répertoire, consiste à définir 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)
C'est vraisemblablement le 0 pour la taille du disque qui empêche iOS d'écrire sur le disque, mais si vous avez une stratégie pour reloadIgnoringLocalCacheData ??code>, la mise en cache de la mémoire ne vous intéresse probablement pas non plus.
Remarque Ceci empêchera tout dossier Caches / Cache.db
(demandes et réponses) ou Caches / fsCachedData /
(données de réponse) être créé du tout. 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 tout en conservant 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)
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 requête génèrera une réponse du serveur avec le même en-tête, ce qui entraînera NSURLCache
. ne pas stocker les données de réponse sur le disque.
Par conséquent, il n’est pas nécessaire d’adopter une 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