截止至本文時(shí), 本文介紹的方法適用范圍: iOS8 ~ iOS13.3
一般來(lái)說(shuō), 我們?cè)陂_(kāi)發(fā)一些緩存或者app下載功能模塊的時(shí)候, 經(jīng)常會(huì)遇到這樣一個(gè)需求:
判斷手機(jī)的剩余存儲(chǔ)空間, 當(dāng)空間不足的時(shí)候, 提示用戶(hù)空間不足
而網(wǎng)上搜索到的方法基本都是如下這種
- (CGFloat)freeDiskSpaceInBytes {
if (@available(iOS 11.0, *)) {
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:[self privatePath]];
NSError *err;
NSDictionary *results = [fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey] error:&err];
if (!results) {
NSLog(@"Error retrieving resource keys: %@%@",[err localizedDescription], [err userInfo]);
abort();
} else {
CGFloat remain = [results[NSURLVolumeAvailableCapacityForImportantUsageKey] floatValue]/1000/1000;
return remain;
}
}
struct statfs buf;
unsigned long long freeSpace = -1;
if (statfs("/var", &buf) >= 0) {
freeSpace = (unsigned long long)(buf.f_bsize * buf.f_bavail);
}
CGFloat space = (CGFloat)(freeSpace*1.0/1024/1024);
return space;
}
這種方法獲取到的剩余存儲(chǔ)空間確實(shí)是 "準(zhǔn)確" 的, 他和你手機(jī)->設(shè)置->關(guān)于本機(jī)里面能看到的那個(gè)數(shù)值是相等的.
然而, 手機(jī)設(shè)置里看到的剩余存儲(chǔ)空間的數(shù)值, 本身就是不準(zhǔn)確的, 這真的是一個(gè)大坑
我實(shí)際開(kāi)發(fā)的過(guò)程中發(fā)現(xiàn), 明明讀取到手機(jī)還有7.2g的剩余空間, 手機(jī)也顯示還有7.2g的剩余空間, 但是 spring_board經(jīng)常會(huì)莫名其妙crash, app應(yīng)用也會(huì)出現(xiàn)一些異常的表現(xiàn), 比如莫名其妙的卡死和發(fā)燙.
后來(lái)發(fā)現(xiàn), 上述情況獲取到的, 只是一個(gè)系統(tǒng)的 "預(yù)估" 內(nèi)存, 并不是實(shí)時(shí)的可用物理空間大小
后來(lái)改用如下方案, 就可以實(shí)時(shí)獲取到真正的物理空間了
- (CGFloat)getNewFreeSize {
uint64_t totalSpace = 0;
uint64_t totalFreeSpace = 0;
NSError *error = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];
CGFloat s = 0;
if (dictionary.count) {
NSNumber *fileSystemSizeInBytes = dictionary[NSFileSystemSize];
NSNumber *freeFileSystemSizeInBytes = dictionary[NSFileSystemFreeSize];
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
s = totalFreeSpace/ (1024.0 * 1024.0);
}
return s;
}
寫(xiě)在最后: 我不知道是iOS13本身的問(wèn)題還是蘋(píng)果所有系統(tǒng)版本的特性. 當(dāng)我用下面這個(gè)相對(duì)準(zhǔn)確的方法獲取物理存儲(chǔ)空間之后, 我發(fā)現(xiàn)隨著我不斷的寫(xiě)入數(shù)據(jù), 他檢測(cè)到的可用空間大小是會(huì)波動(dòng)的, 當(dāng)程序持續(xù)執(zhí)行寫(xiě)入的時(shí)候, 理論上可用空間會(huì)越來(lái)越小, 但是實(shí)際上我觀(guān)察發(fā)現(xiàn): 有好幾次空間已經(jīng)小于我設(shè)計(jì)的閾值500MB了, 過(guò)了一會(huì)兒竟然又反彈到500MB以上, 然后又慢慢變小. 因此感覺(jué)在持續(xù)寫(xiě)入的過(guò)程中, 系統(tǒng)是會(huì)有一套類(lèi)似LRU的策略, 去淘汰掉一些不用的碎片空間的.
當(dāng)然, 以上這段話(huà)是我的猜測(cè).
我是火球貓, 謝謝觀(guān)看我的文章, 有問(wèn)題的話(huà)就留言吧.