1

In iOS 11, I am not able to get the correct free size of the device(disk space) from the Dictionary key NSFileSystemFreeSize. Instead giving 34.4 GB it gives 4 GB free space.

Below is the code I am using

pragma mark - Formatter

- (NSString *)memoryFormatter:(long long)diskSpace
{
    NSString *formatted;
    double bytes = 1.0 * diskSpace;
    double megabytes = bytes / MB;
    double gigabytes = bytes / GB;
    if (gigabytes >= 1.0)
        formatted = [NSString stringWithFormat:@"%.2f GB", gigabytes];
    else if (megabytes >= 1.0)
        formatted = [NSString stringWithFormat:@"%.2f MB", megabytes];
    else
        formatted = [NSString stringWithFormat:@"%.2f bytes", bytes];
    
    return formatted;
}

#pragma mark - Methods

- (NSString *)totalDiskSpace {
    long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
    return [self memoryFormatter:space];
}

- (NSString *)freeDiskSpace {
    long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
    return [self memoryFormatter:freeSpace];
}

- (NSString *)usedDiskSpace {
    return [self memoryFormatter:[self usedDiskSpaceInBytes]];
}

- (CGFloat)totalDiskSpaceInBytes {
    long long space = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize] longLongValue];
    return space;
}

- (CGFloat)freeDiskSpaceInBytes {
    long long freeSpace = [[[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemFreeSize] longLongValue];
    return freeSpace;
}

- (CGFloat)usedDiskSpaceInBytes {
    long long usedSpace = [self totalDiskSpaceInBytes] - [self freeDiskSpaceInBytes];
    return usedSpace;
}
Community
  • 1
  • 1
Jafar Mohammed
  • 103
  • 1
  • 12
  • The results won't be terribly useful. The system manages a bunch of caches and will free up space as more space is needed. For example, if the user has "optimize storage" enabled for their iCloud Photo Library, that could be taking up a huge amount of space, but will be pruned as more space is needed. – bbum Jan 30 '18 at 20:34

4 Answers4

1

OBJECTIVE C (converted)

- (uint64_t)freeDiskspace
{
    uint64_t totalSpace = 0;
    uint64_t totalFreeSpace = 0;

    __autoreleasing NSError *error = nil;  
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];  

   if (dictionary) 
   {  
       NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];  
       NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize];
      totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
      totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
      NSLog(@"Memory Capacity of %llu MiB with %llu MiB Free memory available.", ((totalSpace/1024ll)/1024ll), ((totalFreeSpace/1024ll)/1024ll));
   }

   else 
   {  
      NSLog(@"Error Obtaining System Memory Info: Domain = %@, Code = %d", [error domain], [error code]);  
   }  

   return totalFreeSpace;
}
1

So if people have the problem of not getting the correct free size, use NSURL resourceValuesForKeys to get the free space.

[ fileURL resourceValuesForKeys:@[NSURLVolumeAvailableCapacityForImportantUsageKey ] error:&error];
        
double = availableSizeInBytes = [ results[NSURLVolumeAvailableCapacityForImportantUsageKey] doubleValue ];

Reference Why is `volumeAvailableCapacityForImportantUsage` zero?

Jafar Mohammed
  • 103
  • 1
  • 12
0

Here's how I usually do it

func deviceRemainingFreeSpaceInBytes() -> Int64?
{
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
    guard
        let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: documentDirectory),
        let freeSize = systemAttributes[.systemFreeSize] as? NSNumber
        else {
            // handle failure
            return nil
    }
    return freeSize.int64Value // this returns bytes - scales as required for MB / GB
}
Russell
  • 5,436
  • 2
  • 19
  • 27
0

SWIFT 4:

func getFreeDiskspace() -> UInt64 
{

 let totalSpace: UInt64 = 0

 let totalFreeSpace: UInt64 = 0

 var error: Error? = nil

 let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)

 let dictionary = try? FileManager.default.attributesOfFileSystem(forPath: paths.last ?? "")


if dictionary 
{

 var fileSystemSizeInBytes = dictionary[.systemSize]

 var freeFileSystemSizeInBytes = dictionary[.systemFreeSize]

 totalSpace = fileSystemSizeInBytes as UInt64? ?? 0

 totalFreeSpace = freeFileSystemSizeInBytes as UInt64? ?? 0

 print("Memory Capacity of \((totalSpace / 1024) / 1024) MiB with \((totalFreeSpace / 1024) / 1024) MiB Free memory available.")

}

else
{

 print("Error Obtaining System Memory Info: Domain = \((error as NSError?)?.domain), Code = \(Int(error.code))")



 return totalFreeSpace

}


}
Raj Aryan
  • 363
  • 2
  • 15
  • This is the result i am getting. But isn't this wrong? Memory Capacity of 61025 MiB with 4924 MiB Free memory available. – Jafar Mohammed Jan 30 '18 at 10:18
  • I have 34.3 GB free space left – Jafar Mohammed Jan 30 '18 at 10:20
  • Can you share your full source of code? I am actually out of station else i could help you. – Raj Aryan Jan 30 '18 at 10:22
  • TRY THIS METHOD - (NSDictionary *)attributesOfFileSystemForPath:(NSString *)path error:(NSError **)error – Raj Aryan Jan 30 '18 at 10:25
  • The amount of disk free in the filesystem is not the same as the amount of space available because of aggressive caching in iOS. You'll never get a # back that matches what you see in the Storage UI in Settings (unless you have filled the device with non-purgeable items completely). – bbum Jan 30 '18 at 20:36