好几个月没写博客了,今天试了下产品经理的黑科技。
iOS中经常要对缓存进行操作,包括:
- 缓存清理
- 缓存文件大小显示
- 缓存文件删除
最后本文会介绍一下以前听说过的一个黑科技
同时对一些常用的操作进行了封装,并放到了github上。
先上github地址:https://github.com/StrongX/XCache
1、文件大小读取
第一步就是获取文件路径
NSHomeDirectory()
这个方法会返回应用的沙盒根目录,在这个目录下有三个文件夹:
Documents:应用中用户数据可以放在这里,iTunes备份和恢复的时候会包括此目录
tmp:存放临时文件,iTunes不会备份和恢复此目录,此目录下文件可能会在应用退出后删除
Library/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除
在获取到文件路径之后我们就可以计算文件内容的大小
计算当个文件的大小非常简单,我们可以利用NSFileManager的API直接返回文件大小,像下面这样:
+(long long)returnFileSize:(NSString *)path{
NSFileManager * manager = [ NSFileManager defaultManager ];
return [[manager attributesOfItemAtPath :path error : nil ]fileSize];
}
```
我们只需要传入文件的路径就可以返回文件的大小,唯一需要注意的就是如果文件地下还有子目录的话,我们必须进入子目录挨个计算,所以我们必须对目录进行循环计算:
```
+(long long) folderSizeAtPath:( NSString *) folderPath{
NSFileManager * manager = [ NSFileManager defaultManager ];
if (![manager fileExistsAtPath :folderPath]) return 0 ;
NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath :folderPath] objectEnumerator ];
NSString * fileName;
long long folderSize = 0 ;
while ((fileName = [childFilesEnumerator nextObject ]) != nil ){
NSString * fileAbsolutePath = [folderPath stringByAppendingPathComponent :fileName];
folderSize += [XCache returnFileSize:fileAbsolutePath];
}
return folderSize;
}
```
像这样我们就可以对目录下的每一个子目录进行循环获取到所有的路径,然后通过计算每一个文件的大小,然后全部加在一起就是缓存的大小。
当然在你的工程当中可能你们进行存储的时候有一个固定的目录,同时你知道这个路径,那么当然就不需要进行循环处理了。
OK,像上面那样用两个方法结合在一起就可以计算出一个目录下文件大小了。
--------------------------
2、清理缓存
清理缓存的话,其实和上面的步骤差不多,唯一的区别就是上面是循环计算文件的大小,而这里是循环删除文件。
像下面这样:
```
+(void)deleteFile:(NSString *)path{
NSFileManager * manager = [ NSFileManager defaultManager ];
NSEnumerator *childFilesEnumerator = [[manager subpathsAtPath :path] objectEnumerator];
NSString * fileName;
while ((fileName = [childFilesEnumerator nextObject ]) != nil ){
NSString * fileAbsolutePath = [path stringByAppendingPathComponent :fileName];
[manager removeItemAtPath:fileAbsolutePath error:nil];
}
}
```
和之前循环计算大小的代码类似,只有一行计算大小的代码变成删除文件。我们使用类 NSFileManager
的removeItemAtPath
来删除文件。
-------------------------
3、产品经理的黑科技
因为iOS的沙盒机制,所以所有的app的应用都是相互独立的并不能相互干扰。但是我们聪明的产品经理总是有方法绕过沙盒机制。
当我们的iPhone的内存挤满以后,iOS会自动删除一些缓存文件来释放空间,产品经理们利用这一点,疯狂的向自己应用塞入垃圾文件,当塞满以后iOS就会删除其它应用的缓存文件,随后当然要记得删掉自己之前塞进去的垃圾文件,这样产品们就达到了清理手机空间的目的。(感觉我的iPhone被强奸了)。
以上这个方法可能很多人都听说过,但是可能真的去尝试的人很少,而今天难得放假一天的我,终于有时间来强奸我的iphone了,我真的将我的iPhone弄炸了很多次。
- 首先我用小电影塞满了我的手机,手机只剩下了2G的空间(不然的话写入垃圾文件要好久才能塞满)。
- 然后我写了下面这段代码来强奸我的iPhone:
```
+(void)createLargeCache{
for (int j = 0; j<40; j++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
long long freespace = [XCache freeDiskSpaceInBytes];
for (long long i = freespace*j; freespace>0; i++) {
NSData *cacheData = [NSData dataWithBytesNoCopy:@"我是StrongX 欢迎大家关注我" length:1024*1024*100 freeWhenDone:NO];
[cacheData writeToFile:[NSString stringWithFormat:@"%@/Documents/data%lld",NSHomeDirectory(),i] atomically:true];
freespace-=cacheData.length;
}
});
}
}
```
一口气开了四十个线程,每次写入100MB的文件,这段代码在模拟器上跑的很溜,的确迅速的塞满了模拟器的空间,但是当我真机运行的时候,却发现写入的文件瞬间被删除了(或者在真机上根本没写入,反正就是没达到塞满空间的目的),随后我把NSData换成了一张图片,像这样:
```
+(void)createLargeCache{
for (int j = 0; j<40; j++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
long long freespace = [XCache freeDiskSpaceInBytes];
for (long long i = freespace*j; freespace>0; i++) {
NSData *cacheData = UIImagePNGRepresentation([UIImage imageNamed:@"1.jpg"]);
[cacheData writeToFile:[NSString stringWithFormat:@"%@/Documents/data%lld",NSHomeDirectory(),i] atomically:true];
freespace-=cacheData.length;
}
});
}
}
```
我在主界面不停的监听着应用的缓存大小,果然慢慢的我的应用塞满了手机剩余的2G空间,打开手机的设置页面,手机的剩余容量已经变成了0,强奸了这么久我也累了,然后我去上了个厕所........
上个厕所抽根烟,再打开手机设置页面,我竟然活生生多出了600MB。OMG,产品汪们都是天才啊。!!。。!!!。。!!!!
------------------------
> 此方法慎用:一不容易容易伤及无辜,还有我想知道为什么只多出了600MB!!!我塞了算上小电影差不多40GB,花了这么多功夫才给我腾出了600MB的空间!!!!!
------------------------
以上所有内容我封装成了一个类XCache
/**
* 查询手机剩余内存
*
*/
+ (long long) freeDiskSpaceInBytes;
/**
* 查询缓存大小 单位MB
*
*/
+(NSString *)returnCacheSize;
/**
* 计算单个文件大小
*
* @param path 文件地址
*
*/
+(long long)returnFileSize:(NSString *)path;
/**
* 清理缓存
*
*/
+(void)cleanCache:(void(^)())complete;
/**
* 删除单个文件
*
*/
+(void)deleteFile:(NSString *)path;
/**
* 生成大量垃圾数据
*/
+(void)createLargeCache;
使用起来非常方便,全部都是类方法
github地址:https://github.com/StrongX/XCache
欢迎大家使用并给我点个赞哈,赏个star
------------
最后:前段时间我重新开启了我的个人域名:strongx.cn
以后所有的文章都会首先在我的个人博客发布,欢迎大家关注 StrongX.cn