Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is `volumeAvailableCapacityForImportantUsage` zero?

Tags:

ios

swift

I'm following the Apple's documented example to figure out how to query the available disk space on my device.

I'm using the code below in my applicationDidFinishLaunchingWithOptions:

let fileURL = URL(fileURLWithPath:"/")
do {
    let values = try fileURL.resourceValues(forKeys: [
        .volumeAvailableCapacityKey,
        .volumeAvailableCapacityForImportantUsageKey,
        .volumeAvailableCapacityForOpportunisticUsageKey,
        .volumeTotalCapacityKey
    ])
    print("Available Capacity: \(Float(values.volumeAvailableCapacity!)/1000000000)GB")
    print("ImportantUsage Capacity: \(Float(values.volumeAvailableCapacityForImportantUsage!)/1000000000)GB")
    print("Opportunistic Capacity: \(Float(values.volumeAvailableCapacityForOpportunisticUsage!)/1000000000)GB")
    print("Total Capacity: \(Float(values.volumeTotalCapacity!)/1000000000)GB")
} catch {
    print("Error retrieving capacity: \(error.localizedDescription)")
}

This logs the following:

Available Capacity: 3.665879GB
ImportantUsage Capacity: 0.0GB
Opportunistic Capacity: 0.0GB
Total Capacity: 63.989494GB

Why are volumeAvailableCapacityForImportantUsage and volumeAvailableCapacityForOpportunisticUsage zero and under what circumstances does this happen?

Background:

  • I'm running this experiment on my own 64GB iPhone SE via xCode 10.2.1 (so the total capacity looks correct)
  • My iPhone is running iOS11
  • iTunes claims my device has 10.27GB 'free'
  • I'm trying to figure this out so I know whether my user will have enough space to download a large (40MB+) in-app purchase

Note: This is not the same as this question. I know how to query available space. I want to understand the results of that query.

like image 594
RP-3 Avatar asked Jun 06 '19 09:06

RP-3


1 Answers

The issue is that you're attempting to get the capacity for the system volume at / which is the root of the filesystem. The behaviour of this API is strange but you can get the info you need. If you use your app's documents directory then the FileManager method and .volumeAvailableCapacityKey will still yield strange values but you now get useful values for .volumeAvailableCapacityForImportantUsageKey and .volumeAvailableCapacityForOpportunisticUsageKey.

Example:

let f = ByteCountFormatter()

let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
print("path = \(path)")

let attrs = try! FileManager.default.attributesOfFileSystem(forPath: path)
let fmFree = (attrs[.systemFreeSize] as! NSNumber).int64Value
print("FileManager.attributesOfFileSystem free: \(f.string(fromByteCount: fmFree))")

let docsURL = URL(fileURLWithPath: path)
let values = try! docsURL.resourceValues(forKeys: [.volumeAvailableCapacityKey, .volumeAvailableCapacityForImportantUsageKey, .volumeAvailableCapacityForOpportunisticUsageKey])
print("Volume available capacity: \(f.string(fromByteCount: Int64(values.volumeAvailableCapacity!)))")
print("Volume important available capacity: \(f.string(fromByteCount: values.volumeAvailableCapacityForImportantUsage!))")
print("Volume opportunistic available capacity: \(f.string(fromByteCount: Int64(values.volumeAvailableCapacityForOpportunisticUsage!)))")

On my system this prints:

FileManager.attributesOfFileSystem free: 8.51 GB
Volume available capacity: 8.51 GB
Volume important available capacity: 177.16 GB
Volume opportunistic available capacity: 175.88 GB
like image 51
Sami Samhuri Avatar answered Nov 15 '22 04:11

Sami Samhuri