协议(实现模块)层对缓存机制的支持。
@interface JWCacheURLProtocol : NSURLProtocol<NSURLSessionDataDelegate>
- (void)startLoading{
NSCachedURLResponse *urlResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:[self request]];
if (urlResponse) {
//如果缓存存在,则使用缓存。并且开启异步线程去更新缓存
[self.client URLProtocol:self didReceiveResponse:urlResponse.response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:urlResponse.data];
[self.client URLProtocolDidFinishLoading:self];
[self backgroundCheckUpdate];
}
NSMutableURLRequest *mutableRequest = [[self request] mutableCopy];
[NSURLProtocol setProperty:@YES forKey:URLProtocolAlreadyHandleKey inRequest:mutableRequest];
[self netRequestWithRequest:mutableRequest];
}
重新实现了一次网络请求,并将网络请求的数据进行了一次转发
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[[self client] URLProtocol:self didLoadData:data];
[self appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[[self client] URLProtocol:self didFailWithError:error];
[self setConnection:nil];
[self setData:nil];
[self setResponse:nil];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self setResponse:response];
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; // We cache ourselves.
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[[self client] URLProtocolDidFinishLoading:self];
NSString *cachePath = [self cachePathForRequest:[self request]];
RNCachedData *cache = [RNCachedData new];
[cache setResponse:[self response]];
[cache setData:[self data]];
[NSKeyedArchiver archiveRootObject:cache toFile:cachePath];
[self setConnection:nil];
[self setData:nil];
[self setResponse:nil];
}
@interface RNCachingURLProtocol : NSURLProtocol
- (void)startLoading
{
if (![self useCache]) {
NSMutableURLRequest *connectionRequest =
#if WORKAROUND_MUTABLE_COPY_LEAK
[[self request] mutableCopyWorkaround];
#else
[[self request] mutableCopy];
#endif
// we need to mark this request with our header so we know not to handle it in +[NSURLProtocol canInitWithRequest:].
[connectionRequest setValue:@"" forHTTPHeaderField:RNCachingURLHeader];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:connectionRequest
delegate:self];
[self setConnection:connection];
}
else {
RNCachedData *cache = [NSKeyedUnarchiver unarchiveObjectWithFile:[self cachePathForRequest:[self request]]];
if (cache) {
NSData *data = [cache data];
NSURLResponse *response = [cache response];
NSURLRequest *redirectRequest = [cache redirectRequest];
if (redirectRequest) {
[[self client] URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:response];
} else {
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; // we handle caching ourselves.
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
}
}
else {
[[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotConnectToHost userInfo:nil]];
}
}
}
其它
@return 图片资源
*/
- (void)getData:(GetDataCompletion)completion {
NSURL *url = [NSURL URLWithString:kLastModifiedImageURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];
// // 发送 etag
// if (self.etag.length > 0) {
// [request setValue:self.etag forHTTPHeaderField:@"If-None-Match"];
// }
// 发送 LastModified
if (self.localLastModified.length > 0) {
[request setValue:self.localLastModified forHTTPHeaderField:@"If-Modified-Since"];
}
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// NSLog(@"%@ %tu", response, data.length);
// 类型转换(如果将父类设置给子类,需要强制转换)
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"statusCode == %@", @(httpResponse.statusCode));
// 判断响应的状态码是否是 304 Not Modified (更多状态码含义解释: https://github.com/ChenYilong/iOSDevelopmentTips)
if (httpResponse.statusCode == 304) {
NSLog(@"加载本地缓存图片");
// 如果是,使用本地缓存
// 根据请求获取到`被缓存的响应`!
NSCachedURLResponse *cacheResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
// 拿到缓存的数据
data = cacheResponse.data;
}
// 获取并且纪录 etag,区分大小写
// self.etag = httpResponse.allHeaderFields[@"Etag"];
// 获取并且纪录 LastModified
self.localLastModified = httpResponse.allHeaderFields[@"Last-Modified"];
// NSLog(@"%@", self.etag);
NSLog(@"%@", self.localLastModified);
dispatch_async(dispatch_get_main_queue(), ^{
!completion ?: completion(data);
});
}] resume];
}