清除緩存

@WilliamAlex : 本章重點是如何在第三方框架自己的方法去實現(xiàn)我們想要的效果,同時要學(xué)會怎樣使用工具類和封裝代碼.

關(guān)于"清除緩存",幾乎在每一個App上都能在設(shè)置界面看到清除緩存這個功能,對于我這種初學(xué)者來說,剛開始很難理解緩存這個概念,所以,我決定將它做成一個版塊,方便那些和我一樣剛涉獵iOS的朋友理解,以下內(nèi)容全是自己整理的筆記,如有不對之處,請大神們不吝賜教.

1, 整體思路:

  • 1,首先,需要在根控制器中設(shè)置導(dǎo)航條右邊的"設(shè)置"按鈕

  • 2, 由于前面我已經(jīng)將設(shè)置導(dǎo)航條上的內(nèi)容直接抽取到下面這個方法中了,所以在給"設(shè)置"按鈕背景圖片的同時,我就監(jiān)聽了"設(shè)置"按鈕的點擊.

  • 3, 點擊設(shè)置按鈕之后跳轉(zhuǎn)到設(shè)置界面,所以,需要新建一個繼承于UITableViewController的類,在該類中設(shè)置"清除緩存".

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

    • 4.1,當(dāng)點擊設(shè)置界面中的"清除緩存"對應(yīng)的cell時,將下載的圖片緩存全部從沙盒中清除掉.
    • 4.2, 注意幾個關(guān)鍵詞:1, 點擊cell時清除緩存. 2, 設(shè)置"清除緩存"在tableView中的位置. 3, 顯示沙盒中有多大的緩存值.根據(jù)上面的關(guān)鍵詞,運(yùn)用對應(yīng)的方法來做"清除緩存"操作.
  • 5, 我們既然是從沙盒中獲取緩存值,那么我就需要拿到對應(yīng)沙盒的路徑,根據(jù)路徑獲取對應(yīng)目錄下緩存文件,然后將之清除,做到這這里,我們可以將獲取沙盒路徑,刪除緩存文件等相關(guān)操作都封裝到一個繼承自NSObject的工具類中.

2, 具體步驟

  • 2.1, 在"我"這個根控制器設(shè)置監(jiān)聽按鈕的點擊,然后跳轉(zhuǎn)到"設(shè)置"界面.
在WGMeViewController.m文件中

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

@interface WGMeViewController ()

@end

@implementation WGMeViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 設(shè)置標(biāo)題
    self.navigationItem.title = @"我的";

    // 設(shè)置按鈕
    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)];

    // 將兩個按鈕添加到數(shù)組中
    self.navigationItem.rightBarButtonItems = @[settingButton,nightMoonButton];
}
}
 // 知識拓展: 我的習(xí)慣是將這樣類似的方法抽取成一個分類,可以提高代碼的復(fù)用性

 // 監(jiān)聽導(dǎo)航條上的右邊按鈕的點擊
- (void)settingButtonClick {

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

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

}
  • 2.2, 新建WGSettingViewController類
  • 2.2.1, 這里需要注釋一下: 既然我們最終的目的是獲取到沙盒中緩存,將之清除掉.但是,我們該怎么獲取到沙盒中的緩存內(nèi)存呢?
    在實際開發(fā)中我們大多數(shù)都是使用第三框架,因為它們大大提高了我們的工作效率,一般這樣的框架都是有自己的方法獲取到內(nèi)存緩存,比如:在這個例子中我就使用了"SDWebImage"這個框架,我的習(xí)慣就是去看它的頭文件有沒有關(guān)于內(nèi)存相關(guān)的關(guān)鍵詞,如果有,那么直接點進(jìn)去查看,內(nèi)部有沒有相關(guān)的屬性或者方法拿到我們想要拿到的內(nèi)存緩存.
  • 2.2.1.1, 在pods管理第三方框架的倉庫中直接看到和內(nèi)存相關(guān)的頭文件,點進(jìn)去查看方法或者屬性:剛好有一個獲取緩存的大小的屬性getSize,
  • 2.2.2, 拿到屬性怎么用呢? 繼續(xù)在頭文件中找方法,你會發(fā)現(xiàn)框架內(nèi)部有一個和內(nèi)存有關(guān)的單例

SDImageCache框架中的緩存相關(guān)的方法

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

// 這樣就已經(jīng)很明了了通過調(diào)用單例的getSize屬性來獲取內(nèi)存緩存.
NSInteger cacheSize = [[SDImageCache shareImageCache].getSize];

// 注意:這個方法雖然簡單,但是對初學(xué)者來說,一定要養(yǎng)成這樣的習(xí)慣,不要依賴于教學(xué)視頻(效率不高,實在不懂了,實在沒辦法了才去看看相關(guān)教程)

3, 知識拓展:

  • 2.2.3, 這里需要拓展一下存儲相關(guān)的知識.在開發(fā)的過程中,我們常常會和沙盒打交道,所以我們需要深刻了解沙盒的相關(guān)知識
    • 1, Documents:程序運(yùn)行時,產(chǎn)生的一些持久化的數(shù)據(jù).iTunes同步時,會自動備份該目錄下的所有文件.比如說:游戲應(yīng)用就可以存檔于該目錄下
    • 2, tmp: 保存一些應(yīng)用在運(yùn)行時所需要的"臨時文件"使用完畢之后,會將相應(yīng)的文件刪除掉,甚至在程序沒有運(yùn)行時會自動清除該目錄下的所有文件.最重要的一點"itunes不會同步該目錄下的文件"
    • 3, Library/Caches: 保存應(yīng)用運(yùn)行時生成的一些持久化數(shù)據(jù),"iTunes不會同步該目錄下的文件".一般存儲體積比較大,存儲一些不是很重要的數(shù)據(jù)
    • 4, Library/Preference: 保存應(yīng)用所有的偏好設(shè)置,iOS的settings(設(shè)置)應(yīng)用會在該目錄下找到對應(yīng)的信息,"iTunes會同步設(shè)備時,會備份該目錄".

4, 獲取應(yīng)用沙盒路徑的幾個常見方式:

  // 沙盒的根目錄:
  NSString *home = NSHomeDirectory();
   Documents:
   NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) [0];
// tmp: 臨時文件
NSString *tmp = NSTemporaryDirectory();
// Library/Caches:跟Documents類似的兩種方法,注意下面這個方法的第一個參數(shù),參數(shù)不一樣,獲取的路徑就不一樣,并且獲取到的路徑不是全路徑.
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) [0];
// Library/Preference: 通過NSUserDefaults類存取該目錄下的設(shè)置信息.

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文件中

// 業(yè)務(wù)類:專門處理某個業(yè)務(wù),網(wǎng)絡(luò)請求類,處理文件緩存
// 如何獲取文件尺寸,遍歷文件夾下所有文件,全部加起來.
// 獲取文件夾尺寸,首先需要清除自己是使用的什么下載的圖片,我們一般都是
// 使用一些比較便利的第三方框架,這里使用的是SDWebImage框架,所以需要我會
// 去頭文件中,看看有沒有獲取緩存的方法,注意在獲取緩存大小時,有很多細(xì)節(jié)需要弄清楚,
// 比如:attributesOfItemAtPath只對文件有效,對文件夾無效,所以我們都是要對傳進(jìn)來
// 的路徑拼接和判斷,是否存在,是否路徑是文件夾等等細(xì)節(jié)問題.如果判斷出來的值
// 不對或者說不存在,那么,就需要拋出異常

+ (NSInteger)getCacheSizeOfDirectoriesPath:(NSString *)directoriesPath
{
    // 創(chuàng)建文件管理者(它是一個單例)
    NSFileManager *manager = [NSFileManager defaultManager];

    // 判斷當(dāng)前目錄是否是文件夾或者是否存在
    BOOL isDirectory;
    /**
     * 參數(shù)1: 傳進(jìn)來的路徑directoriesPath
     * 參數(shù)2: 是否是文件夾夾,注意這里的Bool值后面是一個"*",所以這里要傳地址
     */
    BOOL isExist = [manager fileExistsAtPath:directoriesPath isDirectory:&isDirectory];

    // 判斷傳進(jìn)來的路徑對應(yīng)的是否是文件夾或者是否存在,如果不存在或者不是,那么拋出異常
    if (!isDirectory || !isExist) {

        // 拋出異常
        NSException *exception = [NSException exceptionWithName:@"文件路徑不對" reason:@"請重新傳入一個正確的路徑" userInfo:nil];
        [exception raise];
    }
    // 指定一個文件夾路徑,獲取這個文件夾路徑目錄里的所有子路徑
        NSArray *subPaths = [manager subpathsAtPath:directoriesPath];

        // 遍歷所有子路徑,然后拼接拿到全路徑后,通過全路徑,拿到內(nèi)存緩存,將通過子路徑拿到的緩存相加起來就是我們最后要刪除的緩存.
        NSInteger totalCacheSize = 0;

        for (NSString *subPath in subPaths) {

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

        // 判斷當(dāng)前的全路徑是否是隱藏文件,或者不存在甚至是文件夾
        BOOL isDirectory;
        BOOL isExist = [manager fileExistsAtPath:fullFilePath isDirectory:&isDirectory];

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

            // 來到這里,表示它不是隱藏文件,存在以及不是文件夾

            // 拿到文件屬性
            NSDictionary *attribute = [manager attributesOfItemAtPath:fullFilePath error:nil];
            // 獲取每個子路徑的內(nèi)存緩存
            NSInteger cacheSize = [attribute[NSFileSize] integerValue];
            totalCacheSize += cacheSize;
        }
        return totalCacheSize;
}

注意:

  • 上面我是講獲取沙盒路徑的方法封裝到了一個工具類中.
  • 我們只需要在外界調(diào)用這個方法,傳進(jìn)來一個路徑即可.

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];

    // 初始化設(shè)置界面
    [self initSettingViewController];

}

7, 初始化WGSettingViewController

#pragma mark - 初始化設(shè)置界面
- (void)initSettingViewController {

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

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

    [SVProgressHUD showWithStatus:@"正在計算緩存尺寸"];

    // 獲取緩存路徑
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

    // 計算內(nèi)存緩存
     [WGToolFileManager getCacheSizeOfDirectoriesPath:cachePath completeBlock:^(CGFloat totalCacheSize) {

         _totalCacheSize = totalCacheSize;

         [self.tableView reloadData];

         [SVProgressHUD dismiss];
    }];
}

8, 數(shù)據(jù)源方法(用于顯示"清除緩存")

#pragma mark - 數(shù)據(jù)源方法
- (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, 實現(xiàn)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;
}

總結(jié) : 注意在獲取緩存字符串的方法中,在計算顯示內(nèi)存大小時,注意它的單位,1MB = 1000KB 以前在學(xué)校課本里1MB = 1024KB, 1KB = 1024B,理論上是這樣的,但是在實際開發(fā)中,這里的1024一定要換成1000.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末忍啤,一起剝皮案震驚了整個濱河市解恰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)挎峦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來合瓢,“玉大人坦胶,你說我怎么就攤上這事∏缧ǎ” “怎么了顿苇?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長税弃。 經(jīng)常有香客問我纪岁,道長,這世上最難降的妖魔是什么则果? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任幔翰,我火速辦了婚禮,結(jié)果婚禮上西壮,老公的妹妹穿的比我還像新娘遗增。我一直安慰自己,他們只是感情好款青,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布做修。 她就那樣靜靜地躺著,像睡著了一般抡草。 火紅的嫁衣襯著肌膚如雪饰及。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天渠牲,我揣著相機(jī)與錄音旋炒,去河邊找鬼。 笑死签杈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播答姥,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼铣除,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鹦付?” 一聲冷哼從身側(cè)響起尚粘,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敲长,沒想到半個月后郎嫁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡祈噪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年泽铛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辑鲤。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盔腔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出月褥,到底是詐尸還是另有隱情弛随,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布宁赤,位于F島的核電站舀透,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏决左。R本人自食惡果不足惜愕够,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哆窿。 院中可真熱鬧链烈,春花似錦、人聲如沸挚躯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽码荔。三九已至漩勤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缩搅,已是汗流浹背越败。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留硼瓣,地道東北人究飞。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓置谦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亿傅。 傳聞我的和親對象是個殘疾皇子媒峡,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容