PRHTTPURLProtocol.h文件
#import <Foundation/Foundation.h>
//繼承自NSURLProtocol
@interface PRHTTPURLProtocol : NSURLProtocol
@end
PRHTTPURLProtocol.m文件
#import "PRHTTPURLProtocol.h"
#import "PRCachedURLResponse.h"
//自定義唯一標示符
static NSString *const PRHTTPURLProtocolHandledKey = @"PRHTTPURLProtocolHandledKey";
@interface PRHTTPURLProtocol ()
@property (nonatomic, strong) NSURLConnection *connection;//網絡連接對象
@property (nonatomic, strong) NSMutableData *data;//網絡請求返回數據
@property (nonatomic, strong) NSURLResponse *response;//網絡返回封裝對象(包含推盛,數據峦阁,格式,請求鏈接等等)
@end
@implementation PRHTTPURLProtocol
//說白了這個函數是用來過濾網絡請求的協議的小槐,即滿足我設置的協議就給你返回yes拇派,允許你進行網絡通信荷辕,一旦返回no后續(xù)的網絡請求將不會被繼續(xù)執(zhí)行
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
//如果是非http https就不讓他通過
if (![request.URL.scheme isEqualToString:@"http"] && ![request.URL.scheme isEqualToString:@"https"]) {
return NO;
}
//看看是否已經處理過了凿跳,防止無限循環(huán)件豌,如果已經處理過(即設置了允許通過,就不再初始化了)
if ([NSURLProtocol propertyForKey:PRHTTPURLProtocolHandledKey inRequest:request]) {
return NO;
}
return YES;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
- (void)startLoading
{
//如果有緩存控嗜,就直接返回緩存的結果
NSString *cacheKey = self.request.URL.absoluteString;
PRCachedURLResponse *cachedResponse = [[CWObjectCache sharedCache] objectForKey:cacheKey];
if (cachedResponse && cachedResponse.response && cachedResponse.data) {
NSURLResponse *response = cachedResponse.response;
NSData *data = cachedResponse.data;
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
return;
}
//沒有緩存 返回這個新的請求
NSMutableURLRequest *newRequest = [self.request mutableCopy];
[newRequest setTimeoutInterval:15];
//打標簽茧彤,防止無限循環(huán)
[NSURLProtocol setProperty:@YES forKey:PRHTTPURLProtocolHandledKey inRequest:newRequest];
self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self];
}
- (void)stopLoading
{
[self.connection cancel];
}
#pragma mark - NSURLConnection delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
// cache image only
NSString *MIMEType = [response.MIMEType lowercaseString];
if (![MIMEType hasPrefix:@"image"]) {
return;
}
//保存網絡獲取的數據和數據對象
self.data = [[NSMutableData alloc] init];
self.response = response;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[[self client] URLProtocol:self didLoadData:data];
//累加數據
[self.data appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[[self client] URLProtocol:self didFailWithError:error];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[[self client] URLProtocolDidFinishLoading:self];
if (!self.response || [self.data length] == 0) {
return;
}
//緩存對應url的數據和數據對象(序列化)
PRCachedURLResponse *cache = [[PRCachedURLResponse alloc] init];
cache.response = self.response;
cache.data = self.data;
[[CWObjectCache sharedCache] storeObject:cache forKey:[[self.request URL] absoluteString]];
}
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
{
if (response) {
// simply consider redirect as an error
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil];
[[self client] URLProtocol:self didFailWithError:error];
}
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[[self client] URLProtocol:self didReceiveAuthenticationChallenge:challenge];
}
- (void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[[self client] URLProtocol:self didCancelAuthenticationChallenge:challenge];
}
@end