Whether you are creating your own web browser on iOS or just displaying some custom, locally generated HTML,UIWebView
can become a source of lots of frustration, mostly related to its (perceived) lack of basic customization options.
Today, we are going to open the pandora’s box and dive into theFoundation’s URL Loading System to customize every requestUIWebView
sends.
UIWebView
uses the NSURLConnection
class for every request (actually, the NSURLConnection
class was originally written for the first release of Safari, that’s why they are so tied together). And every NSURLConnection
request is intercepted and treated accordingly either by the cache or other custom protocol handlers. By creating a custom protocol handler (using NSURLProtocol
), we can intercept, match and customize every request sent by UIWebView
.
For today’s example, let’s say that we want our UIWebView
on iOS to be seen as a Chrome Desktop browser running on Windows. According toUserAgentString.com the current Chrome user agent is:
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.2 Safari/537.36
So let’s start by creating a subclass of NSURLProtocol
:
|
Whenever the URL Loading system receives a new request, it queries every available protocol handler to determine who can handle that request. Here we use a helper method from NSURLProtocol
, called+propertyForKey:inRequest:
. This method queries for a custom property that can be applied on any NSMutableURLRequest
. On our example, we look for “UserAgentSet”. If the user agent has been set, pass this along. Otherwise, let’s deal with this.
|
On -startLoading
, we create a mutableCopy
of our request and change the User Agent. We must set the “UserAgentSet” property here with +setProperty:forKey:inRequest:
, so we know to pass this request along in the future. After that, we just initiate a new NSURLConnection
with the request.
|
These are the delegates for the NSURLConnection
class, and we must pass them along to our inner client object, contained inside NSURLProtocol
.
Then, we must register this protocol on you App Delegate’s -(BOOL)application:didFinishLaunchingWithOptions:
|
And that’s it!
Of course this only scratches the surface on what can be done with NSURLProtocol
. You can create your own caching mechanism, track redirects (with -connection:willSendRequest:redirectResponse:response:
), sign requests, mock HTTP responses for testing and a lot more.
转自:http://eng.kifi.com/customizing-uiwebview-requests-with-nsurlprotocol/