清除缓存

@WilliamAlex : 本章重点是如何在第三方框架自己的方法去实现我们想要的效果,同时要学会怎样使用工具类和封装代码.

关于"清除缓存",几乎在每一个App上都能在设置界面看到清除缓存这个功能,对于我这种初学者来说,刚开始很难理解缓存这个概念,所以,我决定将它做成一个版块,方便那些和我一样刚涉猎iOS的朋友理解,以下内容全是自己整理的笔记,如有不对之处,请大神们不吝赐教.

1, 整体思路:

  • 1,首先,需要在根控制器中设置导航条右边的"设置"按钮

  • 2, 由于前面我已经将设置导航条上的内容直接抽取到下面这个方法中了,所以在给"设置"按钮背景图片的同时,我就监听了"设置"按钮的点击.

  • 3, 点击设置按钮之后跳转到设置界面,所以,需要新建一个继承于UITableViewController的类,在该类中设置"清除缓存".

  • 4, 理清思路,搭建基本界面

    • 4.1,当点击设置界面中的"清除缓存"对应的cell时,将下载的图片缓存全部从沙盒中清除掉.
    • 4.2, 注意几个关键词:1, 点击cell时清除缓存. 2, 设置"清除缓存"在tableView中的位置. 3, 显示沙盒中有多大的缓存值.根据上面的关键词,运用对应的方法来做"清除缓存"操作.
  • 5, 我们既然是从沙盒中获取缓存值,那么我就需要拿到对应沙盒的路径,根据路径获取对应目录下缓存文件,然后将之清除,做到这这里,我们可以将获取沙盒路径,删除缓存文件等相关操作都封装到一个继承自NSObject的工具类中.

2, 具体步骤

  • 2.1, 在"我"这个根控制器设置监听按钮的点击,然后跳转到"设置"界面.
在WGMeViewController.m文件中

#import "WGMeViewController.h"
#import "WGSettingViewController.h"

@interface WGMeViewController ()

@end

@implementation WGMeViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 设置标题
    self.navigationItem.title = @"我的";

    // 设置按钮
    UIBarButtonItem *settingButton = [UIBarButtonItem barButtonWithImage:@"mine-setting-icon" hightLightImage:@"mine-setting-icon-click" target:self action:@selector(settingButtonClick)];

    // 夜间模式按钮
    UIBarButtonItem *nightMoonButton = [UIBarButtonItem barButtonWithImage:@"mine-moon-icon" hightLightImage:@"mine-moon-icon-click" target:self action:@selector(nightMoonButtonClick)];

    // 将两个按钮添加到数组中
    self.navigationItem.rightBarButtonItems = @[settingButton,nightMoonButton];
}
}
 // 知识拓展: 我的习惯是将这样类似的方法抽取成一个分类,可以提高代码的复用性

 // 监听导航条上的右边按钮的点击
- (void)settingButtonClick {

    WGSettingViewController *settingVc = [[WGSettingViewController alloc] init];

    [self.navigationController pushViewController:settingVc animated:YES];

}
  • 2.2, 新建WGSettingViewController类
  • 2.2.1, 这里需要注释一下: 既然我们最终的目的是获取到沙盒中缓存,将之清除掉.但是,我们该怎么获取到沙盒中的缓存内存呢?
    在实际开发中我们大多数都是使用第三框架,因为它们大大提高了我们的工作效率,一般这样的框架都是有自己的方法获取到内存缓存,比如:在这个例子中我就使用了"SDWebImage"这个框架,我的习惯就是去看它的头文件有没有关于内存相关的关键词,如果有,那么直接点进去查看,内部有没有相关的属性或者方法拿到我们想要拿到的内存缓存.
  • 2.2.1.1, 在pods管理第三方框架的仓库中直接看到和内存相关的头文件,点进去查看方法或者属性:刚好有一个获取缓存的大小的属性getSize,
  • 2.2.2, 拿到属性怎么用呢? 继续在头文件中找方法,你会发现框架内部有一个和内存有关的单例

SDImageCache框架中的缓存相关的方法

+ (SDImageCache *)sharedImageCache {
    static dispatch_once_t once;
    static id instance;
    dispatch_once(&once, ^{
        instance = [self new];
    });
    return instance;
}

// 这样就已经很明了了通过调用单例的getSize属性来获取内存缓存.
NSInteger cacheSize = [[SDImageCache shareImageCache].getSize];

// 注意:这个方法虽然简单,但是对初学者来说,一定要养成这样的习惯,不要依赖于教学视频(效率不高,实在不懂了,实在没办法了才去看看相关教程)

3, 知识拓展:

  • 2.2.3, 这里需要拓展一下存储相关的知识.在开发的过程中,我们常常会和沙盒打交道,所以我们需要深刻了解沙盒的相关知识
    • 1, Documents:程序运行时,产生的一些持久化的数据.iTunes同步时,会自动备份该目录下的所有文件.比如说:游戏应用就可以存档于该目录下
    • 2, tmp: 保存一些应用在运行时所需要的"临时文件"使用完毕之后,会将相应的文件删除掉,甚至在程序没有运行时会自动清除该目录下的所有文件.最重要的一点"itunes不会同步该目录下的文件"
    • 3, Library/Caches: 保存应用运行时生成的一些持久化数据,"iTunes不会同步该目录下的文件".一般存储体积比较大,存储一些不是很重要的数据
    • 4, Library/Preference: 保存应用所有的偏好设置,iOS的settings(设置)应用会在该目录下找到对应的信息,"iTunes会同步设备时,会备份该目录".

4, 获取应用沙盒路径的几个常见方式:

  // 沙盒的根目录:
  NSString *home = NSHomeDirectory();
   Documents:
   NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) [0];
// tmp: 临时文件
NSString *tmp = NSTemporaryDirectory();
// Library/Caches:跟Documents类似的两种方法,注意下面这个方法的第一个参数,参数不一样,获取的路径就不一样,并且获取到的路径不是全路径.
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) [0];
// Library/Preference: 通过NSUserDefaults类存取该目录下的设置信息.

if (![[NSUserDefaults standardUserDefaults] valueForKey:@"isFirst"]) { 
AppGuidViewController *appGuid = [[AppGuidViewController alloc] initWithImageArray:@[@"guies01",@"guies02",@"guies03"] 
startBtnDistanceWithBottomArray:@[@70,@100,@110,@120] needLoadVC:self.viewController]; 
self.window.rootViewController = appGuid; [[NSUserDefaults standardUserDefaults] setValue:@"YES" forKey:@"isFirst"]; 
} else
{ 
self.window.rootViewController = self.viewController; 
}

5, 新建一个工具类:WGFileManagerTool

// 在WGFileManagerTool.h文件中
// 通过文件路径获取到目录文件下的所有文件的大小
+ (NSInteger)getCacheSizeOfDirectoriesPath:(NSString *)directoriesPath;

// 通过文件路径删除目录下所有缓存文件
+ (void)removeDirectoriesPath:(NSString *)directoriesPath;

// 在WGFileManagerTool.m文件中

// 业务类:专门处理某个业务,网络请求类,处理文件缓存
// 如何获取文件尺寸,遍历文件夹下所有文件,全部加起来.
// 获取文件夹尺寸,首先需要清除自己是使用的什么下载的图片,我们一般都是
// 使用一些比较便利的第三方框架,这里使用的是SDWebImage框架,所以需要我会
// 去头文件中,看看有没有获取缓存的方法,注意在获取缓存大小时,有很多细节需要弄清楚,
// 比如:attributesOfItemAtPath只对文件有效,对文件夹无效,所以我们都是要对传进来
// 的路径拼接和判断,是否存在,是否路径是文件夹等等细节问题.如果判断出来的值
// 不对或者说不存在,那么,就需要抛出异常

+ (NSInteger)getCacheSizeOfDirectoriesPath:(NSString *)directoriesPath
{
    // 创建文件管理者(它是一个单例)
    NSFileManager *manager = [NSFileManager defaultManager];

    // 判断当前目录是否是文件夹或者是否存在
    BOOL isDirectory;
    /**
     * 参数1: 传进来的路径directoriesPath
     * 参数2: 是否是文件夹夹,注意这里的Bool值后面是一个"*",所以这里要传地址
     */
    BOOL isExist = [manager fileExistsAtPath:directoriesPath isDirectory:&isDirectory];

    // 判断传进来的路径对应的是否是文件夹或者是否存在,如果不存在或者不是,那么抛出异常
    if (!isDirectory || !isExist) {

        // 抛出异常
        NSException *exception = [NSException exceptionWithName:@"文件路径不对" reason:@"请重新传入一个正确的路径" userInfo:nil];
        [exception raise];
    }
    // 指定一个文件夹路径,获取这个文件夹路径目录里的所有子路径
        NSArray *subPaths = [manager subpathsAtPath:directoriesPath];

        // 遍历所有子路径,然后拼接拿到全路径后,通过全路径,拿到内存缓存,将通过子路径拿到的缓存相加起来就是我们最后要删除的缓存.
        NSInteger totalCacheSize = 0;

        for (NSString *subPath in subPaths) {

            // 拼接全路径
            NSString *fullFilePath = [directoriesPath stringByAppendingPathComponent:subPath];

        // 判断当前的全路径是否是隐藏文件,或者不存在甚至是文件夹
        BOOL isDirectory;
        BOOL isExist = [manager fileExistsAtPath:fullFilePath isDirectory:&isDirectory];

        if ([fullFilePath containsString:@"DS"] || !isExist || isDirectory) continue;

            // 来到这里,表示它不是隐藏文件,存在以及不是文件夹

            // 拿到文件属性
            NSDictionary *attribute = [manager attributesOfItemAtPath:fullFilePath error:nil];
            // 获取每个子路径的内存缓存
            NSInteger cacheSize = [attribute[NSFileSize] integerValue];
            totalCacheSize += cacheSize;
        }
        return totalCacheSize;
}

注意:

  • 上面我是讲获取沙盒路径的方法封装到了一个工具类中.
  • 我们只需要在外界调用这个方法,传进来一个路径即可.

6, WGSettingViewController类中

#import "WGSettingViewController.h"
#import "WGToolFileManager.h"

#import <SVProgressHUD.h>
#import <SDImageCache.h>

static NSString * const ID = @"cache";

@interface WGSettingViewController ()

/** 缓存值大小 */
@property (nonatomic, assign) CGFloat totalCacheSize;

@end

@implementation WGSettingViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 初始化设置界面
    [self initSettingViewController];

}

7, 初始化WGSettingViewController

#pragma mark - 初始化设置界面
- (void)initSettingViewController {

    self.navigationItem.title = @"设置";
    self.view.backgroundColor = WGRGBColor(239, 239, 239);

    // 注册
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];

    [SVProgressHUD showWithStatus:@"正在计算缓存尺寸"];

    // 获取缓存路径
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

    // 计算内存缓存
     [WGToolFileManager getCacheSizeOfDirectoriesPath:cachePath completeBlock:^(CGFloat totalCacheSize) {

         _totalCacheSize = totalCacheSize;

         [self.tableView reloadData];

         [SVProgressHUD dismiss];
    }];
}

8, 数据源方法(用于显示"清除缓存")

#pragma mark - 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    cell.textLabel.text = [self cacheStr:_totalCacheSize];

    return cell;
}

9, 实现tableView的代理方法(点击cell,清除缓存)

#pragma mark - <UITableViewDelegate>

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    // 获取缓存路径
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

    // 删除缓存
    [WGToolFileManager removeCacheSizeOfDirectoriesPath:cachePath];

    _totalCacheSize = 0;

    // 刷新表格
    [self.tableView reloadData];

}

10, 获取缓存字符串

// 获取缓存字符串
- (NSString *)cacheStr:(NSInteger)totalSize
{
    // 获取文件夹缓存尺寸:文件夹比较小,文件夹非常大,获取尺寸比较耗时
    CGFloat cacheSizeF = 0;
    NSString *cacheStr = @"清空缓存";
    if (totalSize > (1000 * 1000)) { //MB
        cacheSizeF = totalSize / (1000 * 1000);
        cacheStr = [NSString stringWithFormat:@"清空缓存(%.1fMB)",cacheSizeF];
        cacheStr = [cacheStr stringByReplacingOccurrencesOfString:@".0" withString:@""];
    } else if (totalSize > 1000) { //KB
        cacheSizeF = totalSize / 1000;
        cacheStr = [NSString stringWithFormat:@"清空缓存(%.1fKB)",cacheSizeF];
    } else if (totalSize > 0){ // B
        cacheStr = [NSString stringWithFormat:@"清空缓存(%ldB)",totalSize];
    }

    return cacheStr;
}

总结 : 注意在获取缓存字符串的方法中,在计算显示内存大小时,注意它的单位,1MB = 1000KB 以前在学校课本里1MB = 1024KB, 1KB = 1024B,理论上是这样的,但是在实际开发中,这里的1024一定要换成1000.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容