[SWIFT] Get available disk space with URL.resourceValues(forKeys:, fromBookmarkData)

Hi,

I'm having trouble figuring out how to use this function to get the available disk space on my iphone. I just don't know how to populate the "fromBookmarkData:" parameter. I can't find an example of it in use anywhere. Here is what I have so far ...


if itemsArray[indexPath.row].fileSize > URL.resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey]
,fromBookmarkData: <#Data#>) {
// alert user not enough space for file
return
}


Thanks

Accepted Reply

First of all, you need to clarify which method you want to call:


- func resourceValues(forKeys: Set<URLResourceKey>) -> URLResourceValues

- static func resourceValues(forKeys: Set<URLResourceKey>, fromBookmarkData: Data) -> URLResourceValues?


I guess you have no intention to work with bookmarks, then use the first.


Second, to use the first method above, which is an instance method, you need to find how to get the instance of `URL` appropriate to use with `URLResourceKey.volumeAvailableCapacityForImportantUsageKey`. It's not clearly documented (see. volumeAvailableCapacityForImportantUsageKey), but some file URL included in the volume you want to inspect would work.


Third, the method is marked as `throws`, so you need to enclose the method call with do-catch and need `try`.


Fourth, the return type of the method is `URLResourceValues`, not an integer type. You need to extract the value of `volumeAvailableCapacityForImportantUsage`. Remember the type of the property is `Optional<Int64>`. You may need to use conditional-binding.


        let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        do {
            let values = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
            if let capacity = values.volumeAvailableCapacityForImportantUsage {
                print(capacity)
                if itemsArray[indexPath.row].fileSize > capacity {
                    // alert user not enough space for file
                    return
                }
                //Continue processing which you want to do when enough capacity available
                //...
            } else {
                print("volumeAvailableCapacityForImportantUsage not available")
                return
            }
        } catch {
            print(error)
            return
        }


A little bit too long than you expect? You may want to write sort of extension or something.

Replies

First of all, you need to clarify which method you want to call:


- func resourceValues(forKeys: Set<URLResourceKey>) -> URLResourceValues

- static func resourceValues(forKeys: Set<URLResourceKey>, fromBookmarkData: Data) -> URLResourceValues?


I guess you have no intention to work with bookmarks, then use the first.


Second, to use the first method above, which is an instance method, you need to find how to get the instance of `URL` appropriate to use with `URLResourceKey.volumeAvailableCapacityForImportantUsageKey`. It's not clearly documented (see. volumeAvailableCapacityForImportantUsageKey), but some file URL included in the volume you want to inspect would work.


Third, the method is marked as `throws`, so you need to enclose the method call with do-catch and need `try`.


Fourth, the return type of the method is `URLResourceValues`, not an integer type. You need to extract the value of `volumeAvailableCapacityForImportantUsage`. Remember the type of the property is `Optional<Int64>`. You may need to use conditional-binding.


        let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        do {
            let values = try url.resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey])
            if let capacity = values.volumeAvailableCapacityForImportantUsage {
                print(capacity)
                if itemsArray[indexPath.row].fileSize > capacity {
                    // alert user not enough space for file
                    return
                }
                //Continue processing which you want to do when enough capacity available
                //...
            } else {
                print("volumeAvailableCapacityForImportantUsage not available")
                return
            }
        } catch {
            print(error)
            return
        }


A little bit too long than you expect? You may want to write sort of extension or something.

Hi @OOPer,


This is so helpful. Thankyou! I had not realized that the version taking only the "forKeys" parameter was an *instance* method. I should have known that. Thanks for pointing it out and showing me how to properly use it.