How to set cache size in UIwebView? - ios

I have an app of UIWebview, I open the webpage A, there are lots of images in webpage A.
so it was very slow when i was first time to open it.
and i opened another webpage B and go back to webpage A, it was very fast and show images directly.
then I opened lots of other webpage and go back to webpage A,
the webpage A was slow again, the webpage A did not change anyghing.
it looks like the uiwebivew cache size is not enough when i opened lots of other webpage,so it delete the old record.
how should i avoid this issue?
Thanks in advance!

See the NSURLCache documentation.
You could be able to set the cache value as follows:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:1000000 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
sharedCache = nil;

Related

Limiting disc and memory cache sizes using NSURLConnection

I have an app that uses UIWebViews. I am using RNCachingURLProtocol to cache pages for offline browsing. RNCachingProtocol uses NSURLConnection in requests. In my AppDelegate I have the following code:
NSUInteger cacheSizeInMemory = 100 * 1024 * 1024;
NSUInteger cacheSizeOnDisc = 100 * 1024 * 1024;
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeInMemory diskCapacity:cacheSizeOnDisc diskPath:#"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];
I have tested the RNCachingProtocol and confirmed that it does cache web content to disc. Since RNCachingURLProtocol uses NSURLConnection, am I to assume that my UIWebView objects will make use of the NSURLCache defined in my AppDelegate? Is there any clear way to test this? Thanks!
UIWebView use shared url cache so yes, [NSURLCache setSharedURLCache:sharedCache]; sets cache that will be used by UIWebView.
The easiest to see this would be subclassing NSURLCache and do something in
-(NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request;
method. Then set your subclass as shared cache and see for yourself.

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

Empty the cache programmatically in 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
}];

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!

Preventing UIWebView to allocate memory indefinitely (NSURLCache apparently not working)

I have been trying to understand how the UIWebView cache works. Since my goal is to be able to manage the memory allocated by the UIWebView (at least, as much as possible), to avoid memory raising indefinitely and the App getting killed because of this.
After reading other stackoverflow questions and searching the web, I decided to try the NSURLCache sharedURLCache, but I cannot figure out how it really works.
My testing scenario is this one:
I have implemented a test app for iOS 5 where I have a single view with a UIWebView inside. This UiWebview is going to load a local index.html file like this:
// Create an NSString from the local HTML file
NSString *fullURL = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"www"];
NSURL *url = [NSURL fileURLWithPath:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
// Load local HTML file
[self.webView loadRequest:requestObj];
In this index.html file, I have a JS script that downloads a JSON from Flickr with the last images uploaded to the their public feed. Each image is appended to a list. This whole process is repeated every second, until we reach 1000 images downloaded from the feed. See the code:
var nImg = 0;
function getData()
{
$.getJSON('http://api.flickr.com/services/feeds/photos_public.gne?format=json&jsoncallback=?', function(data)
{
var items = [];
$.each(data.items, function(i, image) {
items.push('<li id="' + image.title + '"><img src="' + image.media.m + '"/></li>');
});
$('#page > #imagesList').append(items.join''));
nImg += items.length;
});
$('#page > #numImages').html(nImg);
if(nImg < 1000)
setTimeout("getData();", 1000); // Get more data in 1s
}
$(document).ready(function()
{
getData();
});
Finally, in my AppDelegate, I set up the sharedURLCache as written in this post:
// Initialize the Cache, so we can control the amount of memory it utilizes
int cacheSizeMemory = 4*1024*1024; // 4MB
int cacheSizeDisk = 32*1024*1024; // 32MB
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
But, despite what it is supposed to happen, when I open instruments and run the app checking the allocations, the memory keeps growing while we download images (up to 20MB), instead of flattening around 4-6MB as I would expect if the UIWebView would be using this sharedURLCache to cache the images downloaded.
Does anybody know what am I doing wrong? Do I have misunderstood something? Am I loading the page wrong? Does the UIWebView uses another cache for the images loaded in the JS?
Please, let me know your thoughts. I really need to understand how this sharedURLCache works, and how the UIWebView uses it to cache URLRequest, images,... in case it is used at all. I do not want to have an App that uses a UIWebView that can allocate memory without control.
How did you go with this in the end?
I notice that your *sharedCache initWithMemoryCapacity has a diskPath argument that's nil.
From the apple doco:
In iOS, path is the name of a subdirectory of the application’s
default cache directory in which to store the on-disk cache (the
subdirectory is created if it does not exist).
Checkout this link by Two Bit Labs on how to use the cache:
http://twobitlabs.com/2012/01/ios-ipad-iphone-nsurlcache-uiwebview-memory-utilization/
Configuring the shared cache
First off, let’s configure the cache when the app starts (before any requests are made) so we can control the amount of memory it utilizes. In your UIApplicationDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
int cacheSizeMemory = 4*1024*1024; // 4MB
int cacheSizeDisk = 32*1024*1024; // 32MB
NSURLCache *sharedCache = [[[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:#"nsurlcache"] autorelease];
[NSURLCache setSharedURLCache:sharedCache];
...
The above configures a 4MB in-memory cache with a 32MB disk cache. The disk cache will reside in the default iOS cache directory in a sub-directory called “nsurlcache”.
Responding to memory warnings
The most frequent cause of crashes we’ve seen in apps that use web views is being ejected for not freeing up enough memory when a memory warning comes in. When your app receives a memory warning, you should purge the shared cache to free up memory. Do this in your UIApplicationDelegate:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
Now when you run your app in the profiler, you should see the memory utilization flatten out, and if you trigger a memory warning in the simulator you should see the memory usage drop.

Resources