App开发中,经常涉及到清理Cache的功能,特别对于新闻展示类的App,为了提高页面加载速度,大量的数据,需要在本地缓存,当缓存没有一个比较规范的自动清理机制时,会造成程序占用空间越来越大的情况,实时给用户展示当前缓存数据的大小,让用户决定是否手动清理,是一个比较好的机制。最近也给华商韬略的iOS版本,加入了这一功能。
出于数据安全性的考虑,一个应用拥有自己独立的目录,用来写入应用的数据或者首选项参数。应用安装后,会有对应的home目录,home内的子目录功能如下:
可见,我们关于数据的操作来说,主要需要涉及的就是Documents/,以及Library/Cache/,之前一直对Cache目录的理解有点偏差,认为会被应用程序自动清理,其实不然。如果是在启动中需要使用的数据文件,可以放置在Library/Caches/下面,不建议放在Documents目录下,该目录下会备份,耗时。
//获取Cache路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
//获取Documents路径
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
path = [paths objectAtIndex:0];
为了实现离线阅读,需要在本地Cache大量的数据文件,而这些数据文件一般放在Caches目录下,即通常所说的收藏的文章。而其他一些需要清理的Cache,也位于该大目录下面,则需要遍历Caches目录,同时忽略一些特定的文件夹,进行文件大小的统计,进而展现给用户当前Cache的大小。
- (float)checkTmpSize
{
float totalSize = 0;
NSString *path = [self getCachePath];
NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath: path];
for (NSString *fileName in fileEnumerator) {
NSString *filePath = [path stringByAppendingPathComponent: fileName];
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath: filePath error: nil];
unsigned long long length = [attrs fileSize];
if([[[fileName componentsSeparatedByString: @"/"] objectAtIndex: 0] isEqualToString: @"URLCACHE"])
continue;
totalSize += length / 1024.0 / 1024.0;
}
return totalSize;
}
开发中,一般基于NSURLCache来实现数据的Cache,NSURLCache会在Caches目录下,以Bundle Identifier为文件夹名建立Cache的存放路径。可以将该目录下的文件remove,实现清理Cache的功能。而如果使用了SDWebImageManager进行图片加载,也可以顺便使用其封装的清理memory/disk的方法,清理其缓存的数据。
- (void)clearCache
{
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager.imageCache clearDisk];
[manager.imageCache clearMemory];
NSString *identifier = [[NSBundle mainBundle] bundleIdentifier];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *base_path = [self getCachePath];
NSString *path = [NSString stringWithFormat: @"%@/%@", base_path, identifier];
[fileManager removeItemAtPath: path error: nil];
tmpSize = [self checkTmpSize];
[self.tableView reloadData];
}