你能否在UIWebView中拦截NSURLRequests而不会破坏后退按钮?

时间:2021-11-02 23:07:46

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

我无法在不破坏goBack方法的情况下将自定义HTML加载到我的UIWebView中。

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.

我正在拦截我的UIWebView的URL请求,所以我可以加载自定义HTML。我可以控制所有的HTML,所以我有我的特殊应用程序请求使用我可以在webView中解析的自定义方案(即myapp:// arg1 /?arg2 = val):shouldStartLoadWithRequest:navigationType:。我决定加入什么HTML,并调用loadHTMLString:baseURL并返回NO以取消原始请求。

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.

以上工作很棒。问题是我想使用UIWebView的goBack方法和loadRequest:似乎是唯一添加到其历史堆栈的UIWebView方法。

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.

我有一些想法,但我不确定哪些是可行的以及如何解决它们。主要似乎是我必须在webView中返回YES:shouldStartLoadWithRequest:navigationType,我必须使用UIWebView的loadRequest方法。

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.

想法1:修改NSURLRequest / Response:我可以将NSURLRequest子类化,以便(当UIWebView发出请求时)它实际上不会发出HTTP请求并返回带有我的HTML的NSURLResponse吗?或者可能以某种方式修改/子类/将类别方法添加到NSURLResponse?我喜欢它是一个真正的请求,但我担心私有API并被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.)

想法2:处理自定义URL协议注册自定义URL协议,以便我的应用程序响应它,我可以让它返回合法的NSURLResponse(填充我的自定义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?

想法3:愚弄缓存使用此缓存策略创建请求NSURLRequestReturnCacheDataDontLoad然后以某种方式在webView和缓存之间获取我的HTML?

Or maybe I'm on the wrong track completely?

或许我完全走错了轨道?

3 个解决方案

#1


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:

我刚刚测试了另一种非常聪明的方法:只需创建一个自定义NSURLProtocol,而不是修改NSURLCache或重写整个导航历史代码,只要创建HTTP请求,标准NSURLConnection就会使用它。在那里,您可以创建自己的NSURLRequest来加载数据,并可以检查MIME类型,更改请求的内容或根据需要将数据缓存到磁盘。这个想法来自Rob Napier:

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

His code is now also on GitHub:

他的代码现在也在GitHub上:

https://github.com/rnapier/RNCachingURLProtocol

#2


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.

我首先尝试走#3路线。也许在Cocoa with Love上“用本地数据代替远程UIWebView请求”对你有帮助。

#3


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.)

我有#3工作,但它非常,非常脆弱,很难调试。 (例如,Apple会破坏并重新创建NSURLRequests,因此您不能只是继承NSURLRequest并期望在后续响应中完成。)

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

它最终(我)更容易回到自己的历史记录,并注意要加载的页面和滚动位置(垂直屏幕偏移)。

#1


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:

我刚刚测试了另一种非常聪明的方法:只需创建一个自定义NSURLProtocol,而不是修改NSURLCache或重写整个导航历史代码,只要创建HTTP请求,标准NSURLConnection就会使用它。在那里,您可以创建自己的NSURLRequest来加载数据,并可以检查MIME类型,更改请求的内容或根据需要将数据缓存到磁盘。这个想法来自Rob Napier:

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

His code is now also on GitHub:

他的代码现在也在GitHub上:

https://github.com/rnapier/RNCachingURLProtocol

#2


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.

我首先尝试走#3路线。也许在Cocoa with Love上“用本地数据代替远程UIWebView请求”对你有帮助。

#3


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.)

我有#3工作,但它非常,非常脆弱,很难调试。 (例如,Apple会破坏并重新创建NSURLRequests,因此您不能只是继承NSURLRequest并期望在后续响应中完成。)

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

它最终(我)更容易回到自己的历史记录,并注意要加载的页面和滚动位置(垂直屏幕偏移)。