Source: Jingming Babaa
Links: Http://www.jianshu.com/p/03ddcfe5ebd7
Some research on IOS H5 containers (i): comparison and selection of UIWebView and Wkwebview
First, preface
Nsurlprotocol is part of the URL Loading system in iOS. If a developer customizes a nsurlprotocol and registers it with the app, then in this custom Nsurlprotocol we can intercept UIWebView, A system-based nsurlconnection or nsurlsession to encapsulate a network request, and then do a custom response return. Very powerful.
Second, the use of Nsurlprotocol flow
2.1. Register the custom Nsurlprotocol in Appdelegate.
For example, my side of the custom nsurlprotocol called Yxnsurlprotocol.
@Interface yxnsurlprotocol : nsurlprotocol
@End
When the system is loaded, the custom Yxnsurlprotocol is registered to the URL loading system so that all URL requests have access to our custom Yxnsurlprotocol for interception.
- (BOOL)application:(uiapplication *)application Didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {
[nsurlprotocol registerclass:[Yxnsurlprotocol class]];
}
When the loading is complete, when the URL request is generated, it will go into the following related methods of Nsurlprotocol, followed by each of the functions of each method.
2.2. Several methods in Nsurlprotocol
2.2.1, whether to enter the custom Nsurlprotocol loader
+ (BOOL)caninitwithrequest:(nsurlrequest *)request{
BOOL intercept = YES;
NSLog(@"yxnsurlprotocol==%@",request. ) URL. Absolutestring);
if (intercept) {
}
return intercept;
}
Returns YES to the custom loader for processing, and if no is returned without entering the custom selector, the system default behavior is used for processing.
If this step returns YES. It will go into the 2.3 method.
2.2.2, reset the nsurlrequest information
+ (nsurlrequest *)canonicalrequestforrequest:(nsurlrequest *)request {
return request;
}
In this method, we can reset or modify the request information. such as requesting redirection or adding header information, and so on. If there is no special requirement, simply return to request. But because this method is called multiple times in a single request (I don't know for a moment why I need a callback for multiple washes), request redirection and adding header information can also be reset in the Startloading method in the start load.
2.2.3, this method is mainly used to determine whether the two request is the same, if the same can be used to cache data, usually call the implementation of the parent class can be
+ (BOOL)requestiscacheequivalent:(nsurlrequest *)a torequest: (nsurlrequest *)b{
return [super requestiscacheequivalent:a torequest:b ];
}
This method is generally not used.
Where 2.2.4, intercepted requests start to execute
- (void)startloading{
}
This function allows us to focus on the functions used.
2.2.5, end load URL request
- (void)stoploading{
}
2.3. Several methods in Nsurlprotocolclient
The above Nsurlprotocol defines a series of loaded processes. In each process, how we use the URL to load the system as a user is something that nsurlprotocolclient does in several ways.
@Protocol nsurlprotocolclient
Request redirection
- (void)urlprotocol:(nsurlprotocol *)protocol Wasredirectedtorequest :(nsurlrequest *)request Redirectresponse:(nsurlresponse *) redirectresponse;
Whether the response cache is legitimate
- (void)urlprotocol:(nsurlprotocol *)Protocol Cachedresponseisvalid:(nscachedurlresponse *)cachedresponse;
Just received the response information
- (void)urlprotocol:(nsurlprotocol *)protocol didreceiveresponse: (nsurlresponse *)response cachestoragepolicy:(nsurlcachestoragepolicy )policy;
Data loading succeeded
- (void)urlprotocol:(nsurlprotocol *)protocol didloaddata: (nsdata *)data;
Data completion loading
- (void)urlprotocoldidfinishloading:(nsurlprotocol *)protocol;
Data Load Failure
- (void)urlprotocol:(nsurlprotocol *)protocol Didfailwitherror :(nserror *)error;
To start validation for the specified request
- (void)urlprotocol:(nsurlprotocol *)Protocol Didreceiveauthenticationchallenge:(nsurlauthenticationchallenge *)challenge;
Cancels validation for the specified request
- (void)urlprotocol:(nsurlprotocol *)Protocol Didcancelauthenticationchallenge:(nsurlauthenticationchallenge *)challenge;
@End
Third, the implementation of an address redirection demo
This demo implementation of the function is in UIWebView all jump to Sina home page of the request, are relocated to Sohu home.
3.1, the first step, create a new UIWebView, load Sina Home
_webview = [[UIWebView alloc] initwithframe:self. View. Bounds];
_webview. Delegate = self;
[self. View addsubview:_webview];
nsurl *url = [[nsurl alloc] initwithstring:@"https://sina.cn" ];
nsurlrequest *Request = [nsurlrequest requestwithurl:url];
[_webview loadrequest:request];
3.2. Customizing a Nsurlprotocol
@Interface yxnsurlprotocoltwo : nsurlprotocol
@End
3.3, in the appdelegate, to register
- (BOOL)application:(uiapplication *)application Didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {
[nsurlprotocol registerclass:[Yxnsurlprotocoltwo class]];
return YES;
}
3.4. Intercept https://sina.cn/in the Caninitwithrequest method
+ (BOOL)caninitwithrequest:(nsurlrequest *)request{
NSLog(@"Caninitwithrequest url-->%@",request. ) URL. Absolutestring);
//See if it has been processed to prevent infinite loops
if ([nsurlprotocol propertyforkey:urlprotocolhandledkey inrequest: Request]) {
return NO;
}
NSString *urlstring = request. URL. Absolutestring;
if([urlstring isequaltostring:@"https://sina.cn/"]) {
return YES;
}
return NO;
}
3.5. Method redirection in Startloading
- (void)startloading{
nsmutableurlrequest * Request = [self. Request mutablecopy];
//Mark the current incoming request has been intercepted and processed,
//Prevent interception processing at the very beginning
[nsurlprotocol setProperty:@ (YES) forkey:urlprotocolhandledkey inrequest:request];
self. Connection = [nsurlconnection connectionwithrequest: [ Self Changesinatosohu:request] delegate:self];
}
REDIRECT URLs that include Sina in the URL you use to Sohu
- (nsmutableurlrequest *)Changesinatosohu:(nsmutableurlrequest *)request {
NSString *urlstring = request. URL. Absolutestring;
if ([urlstring isequaltostring:@"https://sina.cn/"]) {
urlstring = @"http://m.sohu.com/";
request. URL = [nsurl urlwithstring:urlstring];
}
return request;
}
You can also choose to replace the request with the + (Nsurlrequest) Canonicalrequestforrequest: (nsurlrequest) request. The effect is the same.
3.6, because a new nsurlconnection *connection, so to implement his proxy method, as follows
- (void) connection:(nsurlconnection *)connection Didreceiveresponse :(nsurlresponse *)response {
[self. Client urlprotocol:self didreceiveresponse:response Cachestoragepolicy: nsurlcachestoragenotallowed];
}
- (void) connection:(nsurlconnection *)connection Didreceivedata :(nsdata *)data {
[self. Client urlprotocol:self didloaddata:data];
}
- (void) connectiondidfinishloading:(nsurlconnection *) Connection {
[self. Client urlprotocoldidfinishloading:self];
}
- (void)connection:(nsurlconnection *)connection Didfailwitherror:(nserror *)error {
[self. Client urlprotocol:self didfailwitherror:error];
}
Through the above steps, we can achieve the simplest URL redirection, webview loading Sina homepage, but jumped to Sohu home.
Iv. Summary
With custom Nsurlprotocol, we can do a lot of things after we get the requested request from the user. Like what:
1. Custom Requests and responses
2, the network cache processing (H5 offline package and network picture cache)
3. REDIRECT Network requests
4, provide data mocking function for testing, use local data to return without network.
5. Filter out some illegal requests
6. Fast switching of test environment
7. Block load request, switch to load from local file
8, can intercept UIWebView, based on the system's nsurlconnection or nsurlsession to encapsulate the network request. Currently Wkwebview cannot be intercepted by Nsurlprotocol.
9. When more than one custom Nsurlprotocol is registered to the system, the URL loading process is called sequentially in reverse order of their registration. When one of the Nsurlprotocol intercepts the request, the subsequent nsurlprotocol cannot intercept the request.
V. Contact information
Sina Weibo: Http://weibo.com/5612984599/info
Github:https://github.com/yixiangboy
Welcome to add friends and communicate with each other.
Some research on iOS H5 container (ii): Black Magic under iOS Nsurlprotocol