用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