美文网首页
iOS缓存笔记

iOS缓存笔记

作者: 拥抱月亮的大星星 | 来源:发表于2016-07-25 10:30 被阅读208次

Get请求缓存


iOS 5.0开始,支持磁盘缓存,但仅支持 HTTP
iOS 6.0开始,支持 HTTPS 缓存

// 设置网络缓存 - 4M 的内存缓存 20M 的磁盘缓存,使用默认的缓存路径 Caches/bundleId
    NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
    // 设置全局缓存
    [NSURLCache setSharedURLCache:cache];

上面的两句基本能解决所有的Get请求缓存,而我在自己的某个项目中,清一色的Post请求😂,这TM就尴尬了
今个看到一篇文章,说的是缓存问题,一想到自己做的缓存,存在问题,问题很大。由于我司对于app这一块,貌似也不是很关注,我也不打算改动了,等真正提BUG再改

逻辑漏洞
1.没有想到缓存过期问题
2.撤销缓存问题,现在是一把加载,这个要改改

首先要知道,POST请求不能被缓存,只有 GET 请求能被缓存。因为从数学的角度来讲,GET 的结果是幂等的,就好像字典里的 key 与 value 就是幂等的,而 POST 不 幂等。缓存的思路就是将查询的参数组成的值作为 key ,对应结果作为value。从这个意义上说,一个文件的资源链接,也叫 GET 请求,下文也会这样看待。

  1. 现在我的做法是,让Post也形成Key - value这种,用YYCache缓存

   NSString * urlStr = [NSString stringWithFormat:@"%@%@",baseUrl,sonURl];
    //处理中文和空格问题
    urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    
    //拼接
    NSString * cacheUrl = [self creatUniqueKeyForMD5:urlStr WithDict:paramterDictionary];
//对应的唯一的Key出来了
 NSString * cacheKey = [SystemUtils md5:cacheUrl];

/**
 *  创建一个key
 *
 *  @param urlStr     网址
 *  @param parameters 参数
 *
 *  @return 网址+参数按照一定规律来形成一个key,从而做缓存的MD5转一下,形成特定字符串key
 */
-(NSString *)creatUniqueKeyForMD5:(NSString *)urlStr WithDict:(NSDictionary *)parameters
{
    if (!parameters) {
        return urlStr;
    }
    /**
     *  1.取出来所有Key
     *  2.排序
     *
     *
     *
     */
//    NSMutableArray * lastArray = [NSMutableArray array];
    NSArray * array = [parameters allKeys];
    NSArray * sortArray = [array sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        
        return obj1>obj2;
    }];
    
   __block  NSString * lastString = urlStr;
    [sortArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
        
            lastString = [NSString stringWithFormat:@"%@_%@_%@_",lastString,obj,[parameters objectForKey:obj]];
      
        
        
    }];
  
    
 NSLog(@"%@",lastString);
    
    return lastString;
    
    
    
}

YYcache使用

如果有缓存,并且断网(我们的需求,大家也可以直接加载,等刷新数据再刷新)


    //设置YYCache属性
    YYCache *cache = [[YYCache alloc] initWithName:UserYYKitCache];
    
    cache.memoryCache.shouldRemoveAllObjectsOnMemoryWarning = YES;
    cache.memoryCache.shouldRemoveAllObjectsWhenEnteringBackground = YES;
    
    id cacheData;
    BadNetWork * badWork = [BadNetWork sharedInstance];
    
    if (isCache) {
        
        //根据网址从Cache中取数据
        cacheData = [cache objectForKey:cacheKey];
        
        
        if (cacheData != 0 &&badWork.isConnectNetWork == NO) {
            //将数据统一处理 //如果没有网络并且存在缓存,则加载缓存
            [self returnDataWithRequestData:cacheData Success:^(NSDictionary *requestDic, NSString *msg) {
                YYLog(@"缓存数据\n\n    %@    \n\n",requestDic);
                successed(requestDic);
            } failure:^(NSString *errorInfo) {
                YYLog(@"缓存失败");
                
            }];
            
            
        }
    }  

问题来了》》》缓存失效了怎么办?

完全没考虑好缓存过期问题?等我研究好再来补充。。。待续

仔细看完文章后,来了解两个概念

1.Last-Modified

在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是客户端请求的资源,同时有一个Last-Modified的属性标记此文件在服务器端最后被修改的时间。

Last-Modified格式类似这样:
Last-Modified : Fri , 12 May 2006 18:53:33 GMT
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头,询问该时间之后文件是否有被修改过:
If-Modified-Since : Fri , 12 May 2006 18:53:33 GMT
如果服务器端的资源没有变化,则自动返回 HTTP 304(Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

请求头 响应头
Last-Modified If-Modified-Since

根据实际情况,让你们后台返回这些参数,然后判断即可,如果修改了,这返回HTTP304(Not Changed.)状态码,内容为空,这样就节省了传输数据量。

1.发送请求带上
[request setValue:Modified_value forHTTPHeaderField:@"If-Modified-Since"];

2.收到状态码

3.存储下value
实际上根据自己的来存下
AFN的response在:
 YYLog(@" NSURLSessionDataTask:%@",task.response);

task.response找到Last-Modified用你的方式存储,下次请求的时候,Modified_value的值就是现在你存的

2.ETag(类似我们控制app登录的token,唯一性)

HTTP协议规格说明定义ETag为“被请求变量的实体值”。另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:ETag:"50b1c1d4f775c61:df3"客户端的查询更新格式是这样的:If-None-Match : W / "50b1c1d4f775c61:df3"如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。测试Etag主要在断点下载时比较有用。

思路参考Last-Modified,其中的区别,你可以参考文章
链接

本文大量参考这篇文章,谢谢@ChenYilong

概念性解释来源于😂百度百科😂

相关文章

网友评论

      本文标题:iOS缓存笔记

      本文链接:https://www.haomeiwen.com/subject/edugjttx.html