NSURLCache使用(二)------存储结构

上一篇文章中,我们简单介绍了NSURLCache的使用方法,但是并没有具体分析磁盘存储的具体细节,今天我们来尝试解析一下实际的存储过程的数据组织细节.

2.1 NSURLCache的存储路径

NSURLCache在使用过过程中,我们大概会有两种方式:

  • 使用默认路径:如果没有显式定义NSURLCache或者自定义时没有自定义有效diskPath,系统会默认将缓存保存保存在NSHomeDirectory()目录library/Caches/{bundleid}中;
  • 使用自定义路径:如果显式定义了有效的diskPath,系统就会把请求缓存保存在NSHomeDirectory()目录library/Caches/{bundleid}/{diskPath}中.

2.2 NSURLCache数据存储方式

我们以AFN中AFImagedownloader中的自定义diskPath="com.alamofire.imagedownloader"的方式为例,来做一下分析.

2.2.1 NSURLCache的缓存以何种形式存在?

我们在NSHomeDirectory()目录library/Caches/{bundleid}/{diskPath}中查看一下,就会发现有一个Cache.db文件和fsCachedData的文件夹,证明缓存是以数据库的方式进行了保存.

2.2.2 NSURLCache中都保存了哪些信息?

虽然使用Mac自带的sqlite3工具也可以查看sqlite数据库,但是为了更加直观,我们借助一个DB Browser来查看一下数据库中的数据.

我们看到数据库中有五个表,其中

  • sqlite_sequence:这个是SQLite的系统表,数据库被创建时,sqlite_sequence表会被自动创建。该表包括两列。第一列为name,用来存储表的名称。第二列为seq,用来保存表对应的RowID的最大值.当对应的表增加记录或者删除,该表对应的记录也会自动更新。如果该值超过最大值,会引起SQL_FULL错误;
  • cfurl_cache_schema_version: 用以保存通讯协议版本;

以前两个表信息比较简单,我们不单独做分析.剩余的三张表中,有唯一共有的键entry_ID,所以entry_ID应该是数据库主键,用于连接三张表的信息:

  • cfurl_cache_response:表中包含了主键entry_ID,接口版本号version,哈希值hash_value,缓存策略storage_policy,请求链接request_key,请求时间戳time_stamp,以及分区信息partittion.在这张表中,根据request_key,可以获取到唯一对应的主键entry_ID信息;
  • cfurl_cache_blob_data:主键entry_ID, 请求对象request_object,响应对象response_object, proto_props(暂时不知道是个啥),用户信息user_info.通过DB Broswer我们卡伊看到,键request_object和response_object对应的类型都是BLOB类型,无法直接查看. 我们尝试将对应的value值以二进制数据导出,然后强制以文本格式打开之后发现他们都是以bplist00字符串开头,查询资料可得这其实是一个plist文件,我们可以使用plutil -convert binary1 -o 命令将二进制数据转化为plist文件.可以看出,这个表中缓存了创建requset_object和resposne_object的必要信息,由cfurl_cache_response中的entry_ID可以在该表中获取到创建对应的请求对象和响应对象的必要信息;

转化之后的plist文件大概这个样子:

plutil -convert binary1 -o request.plist request_object.bin
plutil -convert binary1 -o response.plist response_object.bin

  • cfrul_cache_receiver_data:主键entry_ID,缓存数据是否在FS上的标志isDataOnFS,存储路径receiver_data.其中isDataOnFS标志用来表示响应对象的缓存的数据是否存储在FS上,那么FS是个什么呢?我们在Cache.db的同层目录下找到了fsCacheData文件夹,而文件下保存的文件命名与表中receiver_data键对应的值一一对应.如果对应的isDataOnFS为真,则键receiver_data中保存是实际缓存数据在fsCacheData中的位置,也就是缓存数据的文件名.根据entry_ID,可以在该表中找到对应的信息行,如果isDataOnFS为真 ,我们可以根据键receiver_data对应的文件夹在fsCacheData中找到真正的缓存数据.

所以根据上边的探索,缓存的查到大概会是这个样子:

  1. 在cfurl_cache_response中根据request_key(请求接口,即url)查到entry_ID;
  2. 在cfurl_cache_blob_data根据entry_ID找到response_object;
  3. 在cfurl_cache_receiver_data中根据entry_ID找到receiver_data.
  4. 拼接NSCacheURLResponse对象,至此我们就获取到了NSURLCache中的缓存.
NSURLResponse *urlResponse = [[NSURLResponse alloc] initWithURL:request.URL MIMEType:[[request allHTTPHeaderFields] objectForKey:@"Accept"] expectedContentLength:[(NSData *)response_object length] textEncodingName:nil];

NSCachedURLResponse *cachedURLResponse = [[NSCachedURLResponse alloc] initWithResponse:urlResponse data:receiver_data userInfo:nil storagePolicy:NSURLCacheStorageAllowed];

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值