NSCache的特点
- 使用方便,类似字典
- 线程安全
- NSCache的 key 不会被拷贝,不需要实现 Coping 协议
- NSCache自动释放对象
- 手动调用removeObjectForKey:方法
- 手动调用removeAllObjects
- 缓存中对象的个数大于countLimit,或,缓存中对象的总cost值大于totalCostLimit
- 程序进入后台后
- evictsObjectsWithDiscardedContent,这个值与NSDiscardableContent协议有关,默认为YES,当一个类实现了该协议,并且这个类的对象不再被使用时意味着可以被释放
_cache = [[NSCache alloc] init];
NSLog(@"evictsObjectsWithDiscardedContent: %d",_cache.evictsObjectsWithDiscardedContent);
// evictsObjectsWithDiscardedContent: 1
NSCache示例
- 注意:默认情况下,当一个NSPurgeableData对象初始化的时候,它的引用计数变量值为1,并且可以安全的被访问。为了访问这个purgeable memory,仅仅调用 beginContentAccess方法即可。这个方法首先会检查这个对象的数据是否被销毁。如果这个数据仍然在,它将会增加这个对象指向的内存的引用计数,并且返回YES。如果这个对象的数据已经被销毁了,这个方法就会返回NO。当我们完成对这个对象的访问后,调用endContentAccess方法即可,这个方法会减少这块内存区域的引用计数,并允许内存在需要是释放它。只有当 beginContentAccess方法返回YES时,我们才可以去访问这个对象所指向的内存空间
- 当系统可用内存减少时,系统或客户端对象通过调用discardContentIfPossible方法来销毁purgeable数据,当对象所指向的内存引用计数为0时,这个方法仅仅会销毁上面的数据,然后不再做其它任何操作。如果这个内存被销毁了,那么 isContentDiscarded方法会返回YES。
NSURLCache探究
- NSURLRequestCachePolicy 常见缓存策略
-
NSURLRequestUseProtocolCachePolicy 默认的策略。
-
-
NSURLRequestReloadIgnoringLocalCacheData URL应该加载源端数据,不使用本地缓存数据
-
NSURLRequestReturnCacheDataElseLoad Specifies that the
existing cache data should be used to satisfy a URL load request,
regardless of its age or expiration date. However, if there is no
existing data in the cache corresponding to a URL load request,
the URL is loaded from the origin source -
NSURLRequestReturnCacheDataDontLoad Specifies that the
existing cache data should be used to satisfy a URL load request,
regardless of its age or expiration date. However, if there is no
existing data in the cache corresponding to a URL load request, no
attempt is made to load the URL from the origin source, and the
load is considered to have failed. This constant specifies a
behavior that is similar to an “offline” mode.
-
- http中的Cache-Control浅谈
- max-age:缓存时间
- public:谁都可以缓存
- private:只有客户端缓存,中间代理无法缓存
- no-cache:服务端进行确认
- no-store:禁止使用缓存
- Last-Modified
- 服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-Unmodified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不返回资源;如果不一致则返回200和修改后的资源,并带上新的时间。
- If-Modified-Since和If-Unmodified-Since的区别是:
- If-Modified-Since:告诉服务器如果时间一致,返回状态码304
- If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412
- etag
- 单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理。etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。
- If-None-Match和If-Match的区别是:
- If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源
- If-Match:告诉服务器如果不一致,返回状态码412
- 示例
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/img/dong_a16028f60eed614e4fa191786f32f417.gif"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15.0];
//比对服务,资源是否更新
if (self.lastModified) {
[request setValue:self.lastModified forHTTPHeaderField:@"If-Modified-Since"];
}
// if (self.etag) {
// [request setValue:self.etag forHTTPHeaderField:@"If-None-Match"];
// }
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"error warning : %@",error);
}else{
NSHTTPURLResponse *urlRes = (NSHTTPURLResponse *)response;
NSLog(@"response:%ld",(long)urlRes.statusCode);
NSLog(@"---: %@",urlRes);
self.lastModified = [(NSHTTPURLResponse *)response allHeaderFields][@"Last-Modified"];
// self.etag = [(NSHTTPURLResponse *)response allHeaderFields][@"Etag"];
}
}] resume];
- 第二次刷新时根据Last-Modified对比服务器资源
2019-09-25 16:31:25.697014+0800 LGURCacheTest[14904:1023083] response:304
2019-09-25 16:31:25.697164+0800 LGURCacheTest[14904:1023083] ---: <NSHTTPURLResponse: 0x600000bc1620> { URL: https://www.baidu.com/img/dong_a16028f60eed614e4fa191786f32f417.gif } { Status Code: 304, Headers {
"Cache-Control" = (
"max-age=315360000"
);
Connection = (
"Keep-Alive"
);
Date = (
"Wed, 25 Sep 2019 08:31:25 GMT"
);
Etag = (
"\"79353-5933a8157f6dc\""
);
Expires = (
"Sat, 22 Sep 2029 08:31:25 GMT"
);
Server = (
Apache
);
} }
2019-09-25 16:31:25.697242+0800 LGURCacheTest[14904:1023083] ---: (null)