协议(实现模块)层对缓存机制的支持。

@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];
}
posted @ 2017-07-19 16:48  zzfx  阅读(414)  评论(0编辑  收藏  举报