Is it possible to prevent an NSURLRequest from caching data or remove cached data following a request?

Cocoa TouchCaching

Cocoa Touch Problem Overview


On iPhone, I perform a HTTP request using NSURLRequest for a chunk of data. Object allocation spikes and I assign the data accordingly. When I finish with the data, I free it up accordingly - however instruments doesn't show any data to have been freed!

My theory is that by default HTTP requests are cached, however - I don't want my iPhone app to cache this data.

Is there a way to clear this cache after a request or prevent any data from being cached in the first place?

I've tried using all the cache policies documented a little like below:

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

but nothing seems to free up the memory!

Cocoa Touch Solutions


Solution 1 - Cocoa Touch

Usually it's easier to create the request like this

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

Then create the connection

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

and implement the connection:willCacheResponse: method on the delegate. Just returning nil should do it.

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

Solution 2 - Cocoa Touch

I have the same problem in my app when I requested info from twitter. In my case I didn't need to preserve those credentials, so I simple erase them using the next code:

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

I hope it works for somebody :)

Solution 3 - Cocoa Touch

If you use NSURLConnection take a look at the delegate:

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

Return Value

The actual cached response to store in the cache. The delegate may return cachedResponse unmodified, return a modified cached response, or return nil if no cached response should be stored for the connection.

Solution 4 - Cocoa Touch

If you're using NSURLSession, another solution to prevent request and parameters being written to the Cache.db iOS creates within the app's Caches directory, is to set the NSURLCache for the session's configuration to a 0 size memory and 0 size disk cache e.g.

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

or as mentioned above set at a global cache level

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

Presumably it's the 0 for disk size that stops iOS writing to disk but if you have a policy to reloadIgnoringLocalCacheData then you probably aren't interested in memory caching either.

Note This will prevent any Caches/Cache.db (requests & responses) or Caches/fsCachedData/ folder (response data) being created at all. We've decided to take this approach in an app for security purposes as we don't want our requests to be stored on disk cache ever.

If anyone knows is there's a way to stop only request caching but keep response data caching from the iOS URL Loading mechanism, I'd be interested to know. (there's no API or official documentation about this from what I can tell)

Solution 5 - Cocoa Touch

If not specific to a single request(U want disable cache for whole app) below one is the best option.Add this code in app delegate or based on ur need any where

        int cacheSizeMemory = 0; // 0MB
        int cacheSizeDisk = 0; // 0MB
        NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
        [NSURLCache setSharedURLCache:sharedCache];

Solution 6 - Cocoa Touch

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

Assuming the server is correctly implemented, putting the Cache-Control:no-store header in the request will generate a server response with the same header, thus causing NSURLCache to not store the response data on disk.

Therefore, no need for the shotgun approach of disabling NSURLCache disk caching.

PS: Adding the header should work for all HTTP frameworks, like AFNetworking

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNick CartwrightView Question on Stackoverflow
Solution 1 - Cocoa TouchtcurdtView Answer on Stackoverflow
Solution 2 - Cocoa Touchuser186215View Answer on Stackoverflow
Solution 3 - Cocoa TouchcatlanView Answer on Stackoverflow
Solution 4 - Cocoa TouchShagun MadhikarmiView Answer on Stackoverflow
Solution 5 - Cocoa TouchSanjeev RaoView Answer on Stackoverflow
Solution 6 - Cocoa TouchYuri BriganceView Answer on Stackoverflow