為什么要清楚緩存
使用SDWebImage或者AFN都是會有緩存的問題,但是一旦圖片的這些東西多了攀圈,都積壓到緩存文件中去屿聋,這會占用手機的內(nèi)存資源,所以有必要在程序中添加刪除緩存文件的方法或操作浅缸。
相關(guān)的原始文件:https://github.com/gouziqiaoqiao/DeleteBuffer.git
有什么不對的地方,請各位大神指出魄咕。衩椒。。
1.首先明確緩存
明確緩存的意思是知道緩存到底是存放在什么地方的,我們可以在沙盒路徑下查找毛萌。
要知道沙盒目錄下有三個文件夾苟弛,一是Document,二是Library阁将,三是tmp膏秫。而緩存文件一般是存放在Library文件夾下的Caches文件中的,這里里面會放到一些從網(wǎng)絡(luò)請求下來的圖片資源或者是數(shù)據(jù)庫的文件冀痕。
那么找到這些文件的方法可以有,打印沙盒路徑進行查找:
NSString *path = [NSString stringWithFormat:@"%@/Library/Caches", NSHomeDirectory()];
或者是使用簡單粗暴的方式直接找到緩存文件的路徑荔睹,不用進行拼接:
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
2.刪除緩存文件
找到了緩存文件存放的位置就可以對這些文件進行操作了。
操作文件需要獲取文件管理者:
NSFileManager *mgr = [NSFileManager defaultManager];
接下來就是需要判斷緩存路徑是否存在言蛇,如果不存在的話就應(yīng)該拋個異常出來玩玩,如果找到了就執(zhí)行刪除文件的任務(wù)宵距,這樣的話顯得邏輯要縝密一些腊尚。
先拋個異常:
BOOL isDirectory;
BOOL isExist = [mgr fileExistsAtPath:directoryPath isDirectory:&isDirectory];
if (!isExist || !isDirectory) {
// 拋異常
// name:異常名稱
// reason:報錯原因
NSException *excp = [NSException exceptionWithName:@"pathError" reason:@"笨蛋 需要傳入的是文件夾路徑,并且路徑要存在" userInfo:nil];
[excp raise];
}
刪除文件:
// 獲取cache文件夾下所有文件,不包括子路徑的子路徑
NSArray *subPaths = [mgr contentsOfDirectoryAtPath:directoryPath error:nil];
for (NSString *subPath in subPaths) {
// 拼接完成全路徑
NSString *filePath = [directoryPath stringByAppendingPathComponent:subPath];
// 刪除路徑
[mgr removeItemAtPath:filePath error:nil];
}
其實到這這里,只需要調(diào)用響應(yīng)的方法就可以刪除緩存了满哪,刪除緩存就算操作完成了婿斥,但是有的時候可以在刪除緩存的時候提醒用戶,App現(xiàn)目前到底有多大的緩存哨鸭,如果沒有緩存的話民宿,用戶還在進行操作的話,是沒有意義的像鸡,所以可以適當(dāng)考慮下加上緩存文件的大小用于告知用戶活鹰。
3.計算緩存文件的大小
其實這里計算換文件的大小不影響我們緩存文件的操作,只是對用戶展示只估,當(dāng)前App的緩存文件有多大志群,只是一個告知的功能,這一步的操作應(yīng)該是放在刪除緩存之前進行的蛔钙,這樣的邏輯才是順暢的锌云。
這里是要計算緩存的大小,肯定也算是對文件的操作吁脱,也需要拿到文件管理者桑涎,同樣是要判斷路徑是否存在,同樣也是可以拋個異常的兼贡。
但是一旦確認路徑確實是存在后攻冷,就應(yīng)該執(zhí)行的是計算文件大小的操作。計算文件大小紧显,應(yīng)該是一個耗時操作讲衫,如果文件很大,耗時肯定越長,所以這應(yīng)該是放到多線程中去進行操作涉兽。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 獲取文件夾下所有的子路徑,包含子路徑的子路徑
NSArray *subPaths = [mgr subpathsAtPath:directoryPath];
NSInteger totalSize = 0;
for (NSString *subPath in subPaths) {
// 獲取文件全路徑
NSString *filePath = [directoryPath stringByAppendingPathComponent:subPath];
// 判斷隱藏文件
if ([filePath containsString:@".DS"]) continue;
// 判斷是否文件夾
BOOL isDirectory;
// 判斷文件是否存在,并且判斷是否是文件夾
BOOL isExist = [mgr fileExistsAtPath:filePath isDirectory:&isDirectory];
if (!isExist || isDirectory) continue;
// 獲取文件屬性
// attributesOfItemAtPath:只能獲取文件尺寸,獲取文件夾不對,
NSDictionary *attr = [mgr attributesOfItemAtPath:filePath error:nil];
// 獲取文件尺寸
totalSize += fileSize;
}
// 計算完成回調(diào)(為了避免計算大的文件夾,比較耗時,如果直接返回結(jié)果,控制器跳轉(zhuǎn)的時候回產(chǎn)生卡頓,所以采用block回調(diào)的方式)
dispatch_sync(dispatch_get_main_queue(), ^{
if (completion) {
completion(totalSize);
}
});
});
對于得到這個totalSize
來說招驴,可以進一步的操作,不然用戶對于一長串的數(shù)字也是蒙圈的枷畏,所以我們可以對獲取到數(shù)字轉(zhuǎn)成用戶能夠看懂的M
,kB
,B
之類的别厘;
- (NSString *)sizeStr {
NSInteger totalSize = _totalSize;
NSString *sizeStr = @"0.0B";
// MB KB B
if (totalSize > 1000 * 1000) {
// MB
CGFloat sizeF = totalSize / 1000.0 / 1000.0;
sizeStr = [NSString stringWithFormat:@"%.1fMB", sizeF];
} else if (totalSize > 1000) {
// KB
CGFloat sizeF = totalSize / 1000.0;
sizeStr = [NSString stringWithFormat:@"%.1fKB", sizeF];
} else if (totalSize > 0) {
// B
sizeStr = [NSString stringWithFormat:@"%.ldB", totalSize];
}
return sizeStr;
}
只需要在適合的位置進行調(diào)用下這個方法,然后在合適的時間對視圖進行刷新就可以了拥诡。既然刪除之前有文件大小的提示触趴,那么在刪除文件之后也應(yīng)該有相應(yīng)的視圖刷新,不然用戶體驗也不怎么好渴肉。