截止至本文時, 本文介紹的方法適用范圍: iOS8 ~ iOS14.5
一般來說, 我們在開發一些緩存或者app下載功能模塊的時候, 經常會遇到這樣一個需求:
判斷手機的剩余存儲空間, 當空間不足的時候, 提示用戶空間不足
而網上搜索到的方法基本都是如下這種
- (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;
}
這種方法獲取到的剩余存儲空間確實是 "準確" 的, 他和你手機->設置->關于本機里面能看到的那個數值是相等的.
然而, 手機設置里看到的剩余存儲空間的數值, 本身就是不準確的, 這真的是一個大坑
我實際開發的過程中發現, 明明讀取到手機還有7.2g的剩余空間, 手機也顯示還有7.2g的剩余空間, 但是 spring_board經常會莫名其妙crash, app應用也會出現一些異常的表現, 比如莫名其妙的卡死和發燙.
后來發現, 上述情況獲取到的, 只是一個系統的 "預估" 內存, 并不是實時的可用物理空間大小
后來改用如下方案, 就可以實時獲取到真正的物理空間了
- (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;
}
寫在最后: 我不知道是iOS13本身的問題還是蘋果所有系統版本的特性. 當我用下面這個相對準確的方法獲取物理存儲空間之后, 我發現隨著我不斷的寫入數據, 他檢測到的可用空間大小是會波動的, 當程序持續執行寫入的時候, 理論上可用空間會越來越小, 但是實際上我觀察發現: 有好幾次空間已經小于我設計的閾值500MB了, 過了一會兒竟然又反彈到500MB以上, 然后又慢慢變小. 因此感覺在持續寫入的過程中, 系統是會有一套類似LRU的策略, 去淘汰掉一些不用的碎片空間的.
當然, 以上這段話是我的猜測.
我是火球貓, 謝謝觀看我的文章, 有問題的話就留言吧.