views:

7435

answers:

5

I have a simple app loading a site optimized for the iPhone in a UIWebView.

Problem is, caching does not seem to work:

[webView loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: url]
                                       cachePolicy: NSURLRequestUseProtocolCachePolicy
                                   timeoutInterval: 60.0]];

Any things referenced in this remote page (css, images, external javascript files) never get cached (the requests never send a If-Modified-Since header or anything else in the way of cache control.)

Is it possible? It seems with a regular Cocoa WebView there a delegate methods that get called for each resource request and post load (-didFinishLoadingFromDataSource:) which you could use to roll your own caching.. but that does not seem applicable here.

My entire page (page and its referenced resources) is around 89K compressed.. which is slow over 3G in some spots and even worse over EDGE. Incoming requests are at least indicating that it accepts compression (accept-encoding=gzip, deflate), so that's good I suppose.

I read this yui study, which seems to indicate that the iPhone will cache 25k per item. The only thing referenced that is over 25k uncompressed is jquery (packed but uncompressed - it is 30k). Everything else should be cacheable. No request for anything referenced in the page fetched is triggering a 304 on the server side.

That yui study was from almost a year ago, and I am guessing with mobile safari only.

This is using a UIWebView in a native iPhone app.

A: 

The ihone has limited caching capacity compared to a normal computer. It limits uncompressed cache items to 25k.

Good info here: http://yuiblog.com/blog/2008/02/06/iphone-cacheability/

seanb
+2  A: 

You can always perform the requests manually, though that'll be tricky - and then you can cache things to your heart's content. Build a UIWebViewDelegate that starts the request in webView:shouldStartLoadWithRequest:navigationType:, cache the result, and use the UIWebView's loadHTMLString:baseURL: to update the view.

It'll be ugly, and things won't work as smoothly as you might want, but it may be good enough for what you need.

+1  A: 

Any things referenced in this remote page (css, images, external javascript files) never get cached (the requests never send a If-Modified-Since header or anything else in the way of cache control.)

Is it possible? It seems with a regular Cocoa WebView there a delegate methods that get called for each resource request and post load (-didFinishLoadingFromDataSource:) which you could use to roll your own caching.. but that does not seem applicable here.

There's no real answer to this initial question on this thread - does anyone by chance have an answer? We are having the same issue - caching works fine on the initial page load of the html file, but all files referenced from it are not loaded through any delegate we seem to control.

Edit: I found what seems like a way to exploit html5 offline browsing, at this link:

http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone

but really, I feel like I shouldn't have to do that just to cache some pngs and gifs referenced from my page... is there a better way?

I tried this HTML5 solution and it is not working in the UIWebView either, although it is working great in Safari.Does anyone have any experience getting this to work with UIWebView?
+2  A: 

One workaround of this problem as I see is to

1) download HTML code

2) store it in the string

3) find all external links in it like

<img src="img.gif" width="..." height="..." />

4) download them all

5) replace them with embedded Base64-encoded version

<img src="data:image/gif;base64,R0lGODlhUAAPA...JADs= " width="..." height="..." />

6) finally store complete HTML with embedded images as you want.

Genius, although quite disturbing.
Orr Matarasso
+1  A: 

You can now try this:

http://allseeing-i.com/ASIWebPageRequest-a-new-class-for-downloading-complete-webpages

"ASIWebPageRequest is a new experimental addition to the ASIHTTPRequest family. It can be used to download a complete webpage, including external resources like images and stylesheets, in a single request. Once a web page is downloaded, the request will parse the content, look for external resources, download them, and insert them directly into the html source using Data URIS. You can then take the response and put it directly into a UIWebView / WebView on Mac."

I can only advise everyone to use Ben Copsey's great library for all sorts of HTTP operations anyways.

rage