IOS开发 网络发展史(NSURLCach)

时间:2022-11-26 19:08:22

NSURLCach工作原理

1. 请求前的配置,包括请求头,响应头,超时时间以及缓存策略 ( 后面会说到有关缓存策略 ) 。

2. 真正去服务器请求前,判断缓存策略,调用 cachedResponseForRequest: ( NSURLRequest * ) request 方法试着取缓存或者直接请求网络。

3. 如果缓存策略允许取缓存,并且取到了缓存,请求成功并且返回缓存数据。

4. 如果缓存策略允许取缓存,并且没有取到缓存,再次判断缓存策略,如果缓存策略允许联网,则联网请求,否则,请求失败。

5. 上述 23 任何一种请求成功的话,判断缓存策略和服务器返回的响应头。如果允许存储,则调用 storeCachedResponse: ( NSCachedURLResponse * ) cachedResponse forRequest: ( NSURLRequest * ) request 将返回的数据存储到内存以及硬盘,否则,直接返回请求成功。

 

NSURLCach的缓存策略(缓存和请求的*组合)

IOS开发 网络发展史(NSURLCach)

IOS开发 网络发展史(NSURLCach)

IOS开发 网络发展史(NSURLCach)

 

如果使用了默认缓存策略,也就是上面表格中第一个,需要从返回的 response 的 header 中获取相应的字段来指导缓存该如何进行。
1.Cache-Control 字段:常用的有 no-cache,no-store,和 max-age。其中 no-cache 代表不能使用这个缓存,no-store 代表不存储这个数据,max-age 代表缓存的有效期 ( 单位为秒 ) 。

2.Expires 字段:缓存过期时间,后面跟一个日期,此日期之前都可以直接使用本缓存。如果 Expires 与 Cache-Control 同时存在,则 Cache-Control 优先。

3.Last-Modified 和 If-Modified-Since 字段:如果 response 中有 Last-Modified,则在下次请求时,给 request 的 header 设置 If-Modified-Since 为 Last-Modified 的值,服务器校验数据是否有变化,如果有变化,返回新数据,否则,返回 304 状态码,可以使用此缓存。

4.ETag 和 If-None-Match 字段:如果 response 中有 ETag,则在下次请求时,给 request 的 header 设置 If-None-Match 为 ETag 的值,服务器校验数据是否有变化,如果有变化,返回新数据,否则,返回 304 状态码,可以使用此缓存。

 

使用的步骤

1.配置自定义缓存类

NSUInteger memoryCapacity = 20*1024*1024;
NSUInteger diskCapacity
= 50*1024*1024;
WXYURLCache
*customURLCache = [[WXYURLCache alloc] initWithMemoryCapacity:memoryCapacity diskCapacity:diskCapacity diskPath:[WXYURLCache customCachePath]]; [NSURLCache setSharedURLCache:customURLCache];

设置缓存的类型(内存和硬盘),缓存的大小,缓存的位置,缓存的策略

 

2.设置请求

+ (void)requestWithSuccess:(SuccessBlock)success failure:(failureBlock)failure{
 
    AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];
    //配置请求头
    sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer];
    sessionManager.requestSerializer.cachePolicy = [self getCachePolicy];//缓存策略
    //配置响应头
    sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];
 
    [sessionManager GET:customURLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"\n请求成功:\n \nURL:%@\n  \nresponse:%@\n\n", task.currentRequest.URL.absoluteString, responseObject);
        success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"\n请求失败: \n \nURL:%@\n  \nerror:%@\n\n", task.currentRequest.URL.absoluteString, [error.userInfo objectForKey:@"NSLocalizedDescription"]);
        failure(error);
    }];
 
}

 

3.重写缓存的方法(取缓存和存缓存)

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request{
    NSCachedURLResponse *cachedURLResponse = [super cachedResponseForRequest:request];
    id cacheData = nil;
    if (!cachedURLResponse.data) {
        cacheData = @"取到的缓存为空";
    }
    else{
        cacheData = [NSJSONSerialization JSONObjectWithData:cachedURLResponse.data options:NSJSONReadingMutableContainers error:nil];
    }
 
    NSLog(@"\n取缓存:\n  \nURL:%@\n  \nresponse:%@\n\n", request.URL.absoluteString, cacheData);
 
    return cachedURLResponse;
}
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse forRequest:(NSURLRequest *)request{
    id cacheData = [NSJSONSerialization JSONObjectWithData:cachedResponse.data options:NSJSONReadingMutableContainers error:nil];
 
    NSLog(@"\n存缓存:\n  \nURL:%@\n  \nresponse:%@\n\n", request.URL.absoluteString, cacheData);
 
    [super storeCachedResponse:cachedResponse forRequest:request];
}

 

伪造响应

NSLog(@"%@",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]);
    
    
NSURLRequest
*request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:3]; NSURLCache * cache = [NSURLCache sharedURLCache]; NSData *contentData = [@"123" dataUsingEncoding:NSUTF8StringEncoding]; NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[NSURL URLWithString:@"http://172.16.25.44/test1.php"] MIMEType:@"text/html" expectedContentLength:1000 textEncodingName:@"UTF-8"]; NSCachedURLResponse *cacheRespone = [[NSCachedURLResponse alloc] initWithResponse:response data:contentData];
[cache storeCachedResponse:cacheRespone forRequest:request]; connection
= [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];

 

修改响应内容


想要修改内容,要实现NSConnectionDataDelegate方法的willCachResponse方法

-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { NSMutableData *mutableData = [[cachedResponse data] mutableCopy]; //添加数据 NSCachedURLResponse *response = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:mutableData]; return response; }