views:

1738

answers:

3

There's a known problem with embedded UIWebViews that if you load data into them using loadHTMLString or loadData, the canGoBack/canGoForward properties and goBack/goForward methods don't work. These only work when using loadRequest.

Since Safari's normal app cache doesn't work in embedded UIWebViews, creating a native app that effectively caches otherwise live content becomes impossible/unusable. That is, I can cache the contents of the HTML, Javascript, images, etc. and load them via loadHTMLString or loadData, but then the back and forward buttons don't work.

I could also use loadRequest and specify a file URL, but that breaks when it comes to communicating with the live site -- even if I specify a tag (because of cookie domain issues).

I have a work around that involves basically re-implementing the app cache using local store (and not having the native app do any caching itself), which is OK, but not really ideal. Are there any other work arounds/something I missed?

A: 

So do you download the HTML yourself, then pass it to UIWebView as a string? Why so? Do you modify it on the fly or something?

Maybe a custom URL schema would help? You use loadRequest with a schema of your own, which in turn works with HTTP and then feeds the webview whatever data you want?

Seva Alekseyev
I do download the HTML myself and I also download a bunch of images, css, and javascript. I'm manually combining them, but that's not really significant to the issues I'm encountering. The real problem is that we want our native app, which is basically the web app + some enhancements, to load as quickly as possible and relying on the browser is unreliable in terms of performance.Though I'm familiar with custom schemes for launching native apps and with using shouldStartLoadWithRequest, I'm unaware of how to use a custom scheme for loading other types of data. Hints? I'll keep looking.
Brian Westphal
A: 

Could you fetch the content, save it to the local filesystem, point the webview to the local filesystem using file:// URLs, then intercept the link follows with shouldStartLoadWithRequest to fetch more to local fs, point webview at new local content, etc?

I've had good luck with UIWebView and file:/// URLs. Basically you'd be intercepting load requests, fetching stuff yourself, writing it to the local filesystem with rewritten URLs, then loading that into the browser.

There seems to be no way to load/save the browser history.

Nimrod
That does work well for everything until we need authentication to work, which makes use of cookies associated with the normal domain server. I could intercept all of this and basically handle everything myself, but at that point, reimplementing the app cache using local store is just easier -- in fact I've already done that (though it's still not ideal).
Brian Westphal
+1  A: 

I am using the UIWebView's canGoBack to check to see if I'm at the first page of the history. If I am then I just call the little method I used to load the first page (displayLocalResource sets up the HTMLString and loads it into the webView). Here is a snippet:

//Implementing a back button
- (void)backOne:(id)sender{
    if ([webView canGoBack]) {
        // There's a valid webpage to go back to, so go there
        [webView goBack];
    } else {
        // You've reached the end of the line, so reload your own data
            [self displayLocalResource];
        }
    }
Walter
This doesn't work for me :/ displayLocalResource breaks the simulator and canGoBack keeps returning null, even though I'm running local files. Any thoughts?
Andre
displayLocalResource is whatever function you defined to set up the HTML and load it into the webView. You'll have to write the function. I think that canGoBack will always return NULL until you've clicked on a link. This code is in my github repo under OOZWebView.
Walter