用NSURLProtocol。这是个抽象类。这个类不需要去init。所有的代码操作就是覆盖其方法。
这个类能拦截所有的网络请求。
具体用法就是子类化这个类。
使用前先去注册下自己
[NSURLProtocol registerClass:[CDURLProtocol class]];
其他就是继承NSURLProtocol,覆盖NSURLProtocol里的方法;
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
是否去拦截的这个请求,交给你去处理。有点hook的
意思。
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;
规范这个请求。貌似可以在这里更改请求信息。
和上面的方法有一样的说明,必须实现。
This is an abstract method; sublasses must provide an
implementation.
上面的两个方法实现后会调用
- (void)startLoading
从这个开始你自己的网络请求。
用urlconnection去请求自己的请求。
最后的时候,当你离开这个网页是最好调一下这个
+ (void)unregisterClass:(Class)protocolClass;
这个子类的实现方法也没多少,我粘出来吧
#import "CDURLProtocol.h"
@interface CDURLProtocol()
@property(nonatomic,strong)NSURLConnection *connection;
@end
@implementation CDURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
//防止重复请求,UUID 为唯一标示
if ([[NSURLProtocol propertyForKey:@"sssss" inRequest:request] length])
{
return NO;
}else
{
[NSURLProtocol setProperty:[NSUUID new].UUIDString forKey:@"sssss" inRequest:request];
}
//其实放过https请求也可以哦。
// return [scheme isEqualToString:@"https"];
return YES;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
- (void)startLoading
{
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
self.connection = [NSURLConnection connectionWithRequest:mutableReqeust
delegate:self];
[self.connection start];
}
- (void)stopLoading
{
[self.connection cancel];
self.connection = nil;
}
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client
{
self = [super initWithRequest:request cachedResponse:cachedResponse client:client];
return self;
}
/*
自制证书自己实现
*/
//- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
//{
// SecTrustRef trust = challenge.protectionSpace.serverTrust;
// NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
// [challenge.sender useCredential:cred forAuthenticationChallenge:challenge];
//}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self.client URLProtocol:self didFailWithError:error];
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
NSLog(@"currentRequest is %@",connection.currentRequest.URL);
if ([connection.currentRequest.URL.scheme isEqualToString:@"http"]) {
return NO;
}
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if ([connection.currentRequest.URL.scheme isEqualToString:@"http"]) {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
}else
{
//https 能缓存?,我也不太清楚。
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowedInMemoryOnly];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.client URLProtocol:self didLoadData:data];
}
//
//- (nullable NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
//{
//
//
// [self.client URLProtocol:self didReceiveResponse:cachedResponse.response cacheStoragePolicy:cachedResponse.storagePolicy];
//
// return cachedResponse;
//}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self.client URLProtocolDidFinishLoading:self];
}
@end
感觉对这个玩意还不太熟,后期我会持续修改
最后老样子,附上demo
https://pan.baidu.com/s/1slfJolR
修改:2017年02月13日18:56:06
他们说WKWebView 不可用,我试了,可以用。说WK要做很多工作。经我测试:用我写的这个子类,其他工作都不用做。d
demo:
https://pan.baidu.com/s/1miJjdkW