views:

2500

answers:

5

I'd like to be able to use the html5 cache manifest to store images locally on an iPhone that is visiting the page via a UIWebView within an app.

I've set up a sample that I think conforms to the specs, and appears to work in safari 4 and mobile safari, but not in my app's UIWebView.

The sample html is set up at http://bynomial.com/html5/clock3.html.

This is very similar to the sample provided in the HTML5 draft standard.

Here is the entire (non-template) code of the sample app I'm using for testing:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

  // I thought this might help - I don't see any difference, though.
  NSURLCache* cache = [NSURLCache sharedURLCache];
  [cache setDiskCapacity:512*1024];

  CGRect frame = [[UIScreen mainScreen] applicationFrame];
  UIWebView* webView = [[UIWebView alloc] initWithFrame:frame];
  [window addSubview:webView];

  NSString* urlString = @"http://bynomial.com/html5/clock3.html";
  NSURL* url = [NSURL URLWithString:urlString];
  NSURLRequest* request = [NSURLRequest requestWithURL:url];
  [webView loadRequest:request];

  [window makeKeyAndVisible];
}

I've reviewed a few related questions on stackoverflow, but they don't seem to provide info to solve this. For example, I'm pretty sure the files I'm trying to cache are not too large, since they are just a couple small text files (way < 25k).

Any ideas for how to get this to work?

A: 

I'm having the same issue. Works in iphone safari browser, doesn't work in UIWebView. How annoying.

+2  A: 

You could use the cachePolicy param on the NSURLRequest.

request = [NSURLRequest requestWithURL:[NSURL URLWithString:reqString] cachePolicy:NSURLRequestReturnCacheDataDontLoad timeoutInterval: 10.0];

documented here.

Eoin
This doesn't work. Here is how I know: I built a sample file with a cache manifest, and I loaded this file in 3 browsers: (1) Firefox (2) mobile Safari, (3) a UIWebView using NSURLRequestReturnCacheElseLoad (if I use DontLoad then it _never_ loads). Then I modify a cached image on the server. Firefox and Safari both correctly display the old image; my UIWebView gets the new image.
Tyler
+1  A: 

Have you tried to create a customised NSURLCache object and use the setSharedURLCache: method, as recommended in the documentation:

"Applications with more specific needs can create a custom NSURLCache object and set it as the shared cache instance using setSharedURLCache:"

William
Yes I have. It does not cause the cache manifest to work, although you can use that technique to try to create your own cache -- but this is trickier than it sounds like, because the NSURL framework rejects some cached responses for unknown reasons.
Tyler
I've noticed the same thing. It's quite finicky.
Squeegy
+3  A: 

UIWebView's cannot (or will not) use the HTML5 appcache. They just don't. Maybe in iPhone OS 4.0.

But what you can do is fetch all the files yourself with network calls (or just have them in your app bundle) and load up the webview with a local URL pointing to your local HTML file, which can have relative URLs to local assets.

There is no super simple "it just works" way to make this happen, however.

Squeegy
After much investigating, I agree that there simply is no easy way to solve this problem.The closest I could get was to implement my own subclass of NSURLCache and set that as the cache. However, even with all that, I found that often my cached results were rejected by the OS for reasons which were opaque to me. It seems that the OS is extremely picky about accepting cached responses, no matter what cache policy or other parameter tweaks I attempted. Quite frustrating to work with!
Tyler
+4  A: 

I got this to work using a .manifest file in a UIWebView. I discovered the trick on the Apple developer forums.

you must deliver the proper mime-type for the manifest file: it must be of type "text/cache-manifest" - if it is anything else, then you won't get your files cached.

you can use web-sniffer at http://web-sniffer.net/ to look at the headers returned by your server.

if you are using .htaccess files on your web server, then add the following line to the .htaccess file:

AddType text/cache-manifest .manifest

make sure to clear your browser cache after making this change to see the effect.

HTH Mark

edit: this is only supported on iOS 4.0 and later. You will need to implement your own caching mechanism for iOS 2.x and 3.x :-(

iPixFolio