I'm trying to get the total / used / free space from my iOS app in bytes, using the following code, adapted from various solutions on this website.
- (unsigned long long)totalDiskSpace {
unsigned long long space = 0;
NSError *error = nil;
NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:paths.lastObject error:&error];
if (dict) {
NSNumber *size = dict[NSFileSystemSize];
space = size.unsignedLongLongValue;
}
return space;
}
- (unsigned long long)freeDiskSpace {
unsigned long long space = 0;
NSError *error = nil;
NSArray<NSString *> *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSDictionary *dict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:paths.lastObject error:&error];
if (dict) {
NSNumber *size = dict[NSFileSystemFreeSize];
space = size.unsignedLongLongValue;
}
return space;
}
The issue is, when I compare the values to what the use might see in their Settings.app, they're totally off I'm testing on a 256 GB iPhone X, and while the "total" space value is correct, the value for "free" space seems be a lot less than it should be.
On my device, I'm getting a value of 255937040384
(~255GB), but only 175536754688
for Free, which translates to 80400285696
used (~80GB). BUT, in Settings.app, my device shows only 52.4 GB used.
Anyone know why that may be?
Instead of using NSFileManager
, use NSURL
's resourceValuesForKeys:
method to get your drive's free space. NSURL
provides three relevant constants here:
NSURLVolumeAvailableCapacityKey
—the literal free space on your drive, which should be identical to the value returned by NSFileManager
,
NSURLVolumeAvailableCapacityForImportantUsageKey
—the literal free space on your drive, plus the size of any "ephemeral" files on the disk which can be automatically deleted if needed to provide room for other things, and:
NSURLVolumeAvailableCapacityForOpportunisticUsageKey
—the amount of space available for ephemeral files themselves, which in my experience is usually something less than the actual free space.
In your case, NSURLVolumeAvailableCapacityForImportantUsageKey
is probably the value that Settings.app is reporting, since from a user standpoint, that is the amount of space that you have to work with.
Also, as a general rule, if you are using an Apple Objective-C or Swift API that takes a path rather than a URL, it's probably a legacy API. The URL-based APIs are usually more complete and up-to-date, and should be generally preferred over the path-based ones—in this case, the path-based API predating the Important/Opportunistic concept causes it to lack the facilities for reading those values.