Can you intercept NSURLRequests in a UIWebView without breaking the back button?
Asked Answered
W

3

13

I'm having trouble loading custom HTML into my UIWebView without breaking its goBack method.

What Works

I'm intercepting the URL requests of my UIWebView so I can load custom HTML. I have control over all the HTML, so I have my special app requests use a custom scheme (ie. myapp://arg1/?arg2=val) that I can parse in webView:shouldStartLoadWithRequest:navigationType:. I decide what HTML I really want to load and call loadHTMLString:baseURL and return NO to cancel the original request.

What Doesn't Work

The above works great. The problem is that I want to make use of the UIWebView's goBack method and loadRequest: appears to be the only UIWebView method that adds to its history stack.

I have a few ideas, but I'm not sure which are feasible and how to go about them. The main thing seems to be that I have to return YES in webView:shouldStartLoadWithRequest:navigationType and I have to use UIWebView's loadRequest method.

Idea 1: Modify NSURLRequest/Response: Can I subclass NSURLRequest so that (when the UIWebView makes the request) it doesn't actually make an HTTP request and returns an NSURLResponse with my HTML in it? Or maybe modify/subclass/add a category method to NSURLResponse somehow? I like the idea of it being a real request, but I'm concerned about private APIs and being rejected from the App Store.

Idea 2: Handle a custom URL Protocol Register a custom URL protocol so my app responds to it and I can have it return a legitimate NSURLResponse (filled with my custom HTML.)

Idea 3: Fool the cache Create the request with this cache policy NSURLRequestReturnCacheDataDontLoad and then somehow get my HTML in between the webView and the cache?

Or maybe I'm on the wrong track completely?

Wikiup answered 24/1, 2011 at 2:18 Comment(1)
Did you come up with a good solution? If so, what was it?Gelb
W
1

I would recommend against any of the above approaches.

I got #3 working, but it was very, very fragile and hard to debug. (For example, Apple destroys and re-creates NSURLRequests, so you can't just subclass NSURLRequest and expect to come through in the subsequent response.)

It ended up being (much) easier to my own back history and note what page to load and scroll position (vertical screen offset).

Wikiup answered 23/11, 2011 at 18:31 Comment(1)
Thanks for answering. I've decided to try the local cache suggestion from Cocoa with Love suggested by Ortwin. So far it seems to be doing what I need and seems to be fairly robust.Gelb
B
7

There is another really clever approach which I just tested out: Instead of tinkering with the NSURLCache or rewriting the entire navigation history code, just create a custom NSURLProtocol which is used by the standard NSURLConnection whenever a HTTP request is made. There, you create your own NSURLRequest to load the data and can inspect the MIME type, change the content of the request or cache your data to disk as you please. This idea comes courtesy of Rob Napier:

http://robnapier.net/blog/offline-uiwebview-nsurlprotocol-588

His code is now also on GitHub:

https://github.com/rnapier/RNCachingURLProtocol

Bennet answered 11/7, 2012 at 11:22 Comment(1)
Thanks for posting those links. It's definitely something I'm still interested in.Wikiup
F
5

I'd first try to go route #3. Maybe "Substituting local data for remote UIWebView requests" on Cocoa with Love is helpful for you.

Fite answered 31/1, 2011 at 11:6 Comment(0)
W
1

I would recommend against any of the above approaches.

I got #3 working, but it was very, very fragile and hard to debug. (For example, Apple destroys and re-creates NSURLRequests, so you can't just subclass NSURLRequest and expect to come through in the subsequent response.)

It ended up being (much) easier to my own back history and note what page to load and scroll position (vertical screen offset).

Wikiup answered 23/11, 2011 at 18:31 Comment(1)
Thanks for answering. I've decided to try the local cache suggestion from Cocoa with Love suggested by Ortwin. So far it seems to be doing what I need and seems to be fairly robust.Gelb

© 2022 - 2024 — McMap. All rights reserved.