Empty the cache programmatically in iOS - ios

Does anyone by coincidence know how I can empty the cache memory of the iOS app that I am developing, in the moment it goes to the background (applicationDidEnterBackground)? I have investigated about NSCache but I am still not able to understand how could I retrieve the cache to basically remove/free it?

Is this what you're talking about?
[[NSURLCache sharedURLCache] removeAllCachedResponses];
You can also modify the cache behavior of your requests to selectively cache responses. If you're using AFNetworking by chance, you can use setCacheResponseBlock. E.g. in one project I set it to return nil for all large video and audio files. But allow it to cache smaller image files.
[streamingOperation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
return nil; // Ensures we are not unecessarily caching asset data to Cache.db
}];

Related

Is it possible to clear only the in memory cache in a NSURLCache?

This post recommends doing this:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
However, that will take both the on disk and the in memory cache. Does something like this work to just evict the in memory cache?
NSURLCache *cache = [NSURLCache sharedURLCache];
NSUInteger currentMemoryCapacity = cache.memoryCapacity;
// Not sure if this works? Docs seem to say it will trigger an evict.
// https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Classes/NSURLCache_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLCache/setMemoryCapacity:
cache.memoryCapacity = 0;
cache.memoryCapacity = currentMemoryCapacity;
Yes, that code should evict the memory cache. (And does on iOS 7.1.1, in my brief test.)
If you're looking for finer control over the cache, check out Peter Steinberger's fork of SDURLCache which has (for example) a -removeAllCachedResponsesInMemory method.
This no longer appears to work (tested on the iOS 9.2 simulator)
Although the cache's reported memoryCapacity changes, the actual memoryUsage reported doesn't :-(

Caching on AFNetworking 2.0

So here's the deal. I recently started using AFNetworking to download a few files on start using the following code:
NSMutableURLRequest* rq = [api requestWithMethod:#"GET" path:#"YOUR/URL/TO/FILE" parameters:nil];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:rq] autorelease];
NSString* path=[#"/PATH/TO/APP" stringByAppendingPathComponent: imageNameToDisk];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"SUCCCESSFULL IMG RETRIEVE to %#!",path)
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// Deal with failure
}];
With my path actually plugged into the path variable (Sorry, not on the right computer right now to actually copy pasta the text, but it's exactly the same as the above with different path stuffs)
And everything is working great! I'm getting the file successfully downloaded and everything. My current issue is that I'm trying to get caching to work, but I'm having a lot of difficulties. Basically, I'm not sure what I actually have to do client side as of AFNetworking 2.0. Do I still need to set up the NSURlCache? Do I need to set the caching type header on the request operation differently? I thought that maybe it was just entirely built in, but I'm receiving a status of 200 every time the code runs, even with no changes in the file. If I do have to use the NSUrlCache, do I have to manually save the e-tag on the success blocks requestoperation myself and then feed that back in? Any help on how to progress would be much appreciated. Thanks guys!
AFNetworking uses NSURLCache for caching by default. From the FAQ:
AFNetworking takes advantage of the caching functionality already provided by NSURLCache and any of its subclasses. So long as your NSURLRequest objects have the correct cache policy, and your server response contains a valid Cache-Control header, responses will be automatically cached for subsequent requests.
Note that this mechanism caches NSData, so every time you retrieve from this cache you need to perform a somewhat expensive NSData-to-UIImage operation. This is not performant enough for rapid display, for example if you're showing images in a UITableView or UICollectionView.
If this is the case, look at UIImageView+AFNetworking, which adds downloads and caching of UIImage objects to UIImageView. For some applications you can just use the out-of-the-box implementation, but it is very basic. You may want to look at the source code for this class (it's not very long) and use it as a starting point for your own caching mechanism.

How to cache file downloads with AFNetworking?

I am trying to download some files.
For each cell, I check if the file exists and is already stored in a directory, if not I download it.
But I also download files for the next couple of cells.
What happens, if I am trying to download a file for an invisible cell ahead of time, but then the user scrolls to the cell and the file is not fully downloaded yet.
Is there anyway to prevent it from downloading twice?
Is there anyway to know that the file is already getting downloaded?
I am using AFNetworking.
What you're trying to do has a name and it's caching.
AFNetworking already implements it as per the official FAQs
Does AFNetworking have any caching mechanisms built-in?
AFNetworking takes advantage of the caching functionality already provided by NSURLCache and any of its subclasses. So long as your NSURLRequest objects have the correct cache policy, and your server response contains a valid Cache-Control header, responses will be automatically cached for subsequent requests.
Set up the cache as follows and you'll be ok
- (void)setupCache {
NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:1024*1024*4 // 1MB mem cache
diskCapacity:1024*1024*5 // 5MB disk cache
diskPath:nil];
[NSURLCache setSharedURLCache:urlCache];
}
Then just perform requests normally and if the resource is in cache you'll get a cache hit and you won't be downloading it twice.
Note that if you have to support anything below iOS5, you have to use an alternative URL cache like SDURLCache and set it up like follows
- (void)setupCache {
SDURLCache *urlCache = [[SDURLCache alloc] initWithMemoryCapacity:1024*1024 // 1MB mem cache
diskCapacity:1024*1024*5 // 5MB disk cache
diskPath:[SDURLCache defaultCachePath]];
[NSURLCache setSharedURLCache:urlCache];
}
The reason is well explained in this article, but it can be summarized by the following quote:
Before iOS5, NSURLCache just saved requests to memory, even if the documentation said otherwise - the diskCapacity property was silently ignored

UIWebview caching to disk

I have a simple iOS app that loads and list of links and presents them in a UIWebview. The app, when installed, is ~2MB. After clicking around through some of the links, I noticed that the disk usage of documents and data jumped to over 10MB. As a couple days went on, I noticed the disk usage continued to grow. My question is, what is the best way to manage disk storage on iOS?
The goal of this app is to be very minimal and not heavy on resources, but I'm concerned that it will continue to consume more and more disk space with, what I assume is, cached web content. Should I / is there a way to set a cache size? Or does iOS just handle this for me and delete old data eventually?
Do not optimize prematurely! Resources on disk put no strain on RAM memory, so don't worry about it. If the system is managing caching for you, it is not up to you to guess what it will do. If it needs to clear space, it will presumably clear space. Don't worry, be happy.
Now, having said, you do get some control over a NSURLRequest caching policy. Look at the NSURLRequest docs to learn more about that.
Specify cache size:
int cacheSizeMemory = 8 * 1024 * 1024; // 8MB
int cacheSizeDisk = 32 * 1024 * 1024; // 32MB
NSURLCache* sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:#"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
Remove all stored cached URL responses:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
Hope to be useful to you!

NSURLCache and .svg files

I am caching locally some of the larger files required for a UIWebView and have a subclass of NSURLCache with a custom implementation to help serve these files.
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
I am using this to hijack the requests and return a locally stored copy of the files (mainly t
The body of cachedResponseForRequest:request (without the boiler plate) is essentially:
// logic to figure out what the local file is, load it into a NSData object (f)
NSURLResponse *r = [[NSHTTPURLResponse alloc] initWithURL:request.URL MIMEType:mimetype expectedContentLength:[f length] textEncodingName:nil];
NSCachedURLResponse *cr = [[NSCachedURLResponse alloc] initWithResponse:r data:f] ;
[super storeCachedResponse:cr forRequest:request];
return cr;
This works correctly for all of the cached content apart from a single svg image. When the svg image is attempted to load it will proceed through cachedResponseForRequest:request, build a NSCachedURLResponse object and return it.
However the next thing the application does is download the file from the remote server and then any subsequent request are served from the cache. We dont want to download the file remotely as its relatively large and impacts performance.
Does the NSURLCache deal with .svg files differently to other filetypes?
The maximum size of files that will be handled by the NSUrlCache can be influenced by the parameters when you initialize the cache with:
initWithMemoryCapacity:(NSUInteger)memoryCapacity diskCapacity:(NSUInteger)diskCapacity diskPath:(NSString *)diskPath
The maximum file size is related to the memoryCapacity. You should set that to at least 10 (why?) times the maximum file size that you want to handle.
I have tried this with files up to 15MB using https://github.com/evermeer/EVURLCache

Resources