Kodeco Forums

FileManager Class Tutorial for macOS: Getting Started with the File System

In this tutorial, learn to use the FileManager class in a macOS app. Work with files, folders and navigate the file system while creating a working app.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/666-filemanager-class-tutorial-for-macos-getting-started-with-the-file-system
1 Like

This tutorial is great!
Thanks.

Just wondering how the urlForDataStorage() method is connected to the quit File Spy command. Many thanks for the wonderful tutorial

Sorry worked it out, its the saveCurrentSelections() function triggered by viewWillDisappear(). Will think before I post next time. Many thanks again

In ViewController.swift, the viewWillDisappear() method is called automatically when the app is closing and it then calls saveCurrentSelections(). saveCurrentSelections() calls urlForDataStorage() which saves your current settings if possible.

Hi Sarah! I need to upload files(doc, images, pdf, etc) on server, selected through my macOS. Can you plz help me with this? I want to do it using swift.

Fantastic tutorial Sarah!! Bravo Zulu!!

Hi Sarah,

Is there a (key,value) pair to get the size and space used of a volume? If not, how does one do that?

Thanks

I do that with the URLResourceKeys .volumeAvailableCapacityKey and .volumeTotalCapacityKey.
Here is a chunk of a playground that shows the spaces for attached drives.

import Foundation

let keys: [URLResourceKey] = [.volumeAvailableCapacityKey, .volumeTotalCapacityKey]
let volumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: keys, options: [])!

let byteFormatter = ByteCountFormatter()
byteFormatter.countStyle = .file

for url in volumes {
    if let capacities = try? url.resourceValues(forKeys: [.volumeAvailableCapacityKey, .volumeTotalCapacityKey]) {
        if let totalBytes = capacities.volumeTotalCapacity,
            let availableBytes = capacities.volumeAvailableCapacity, totalBytes > 0 {
            let total = byteFormatter.string(fromByteCount: Int64(totalBytes))
            let available = byteFormatter.string(fromByteCount: Int64(availableBytes))

            print("\(url.path) - \(available) available, \(total) total.")
        }
    }
}

Uploading to a server isn’t really in the scope of this tutorial, but I suggest you look at the docs for URLSession and URLSessionUploadTask.

Hi Sarah,

Works like a charm. I want to work with network volumes only but Swift is being “Citizen Un-cooperative”. I have the following…

let networkVolume = try? url.resourceValues(forKeys: [.volumeIsRootFileSystemKey])

if networkVolume?.volumeIsRootFileSystem == nil {
if let capacities = try? url.resourceValues(forKeys: [.volumeAvailableCapacityKey, .volumeTotalCapacityKey]) {
if let totalBytes = capacities.volumeTotalCapacity,
let availableBytes = capacities.volumeAvailableCapacity, totalBytes > 0 {
let total = byteFormatter.string(fromByteCount: Int64(totalBytes))
let available = byteFormatter.string(fromByteCount: Int64(availableBytes))

                    print("\(url.path) - \(available) available, \(total) total.")
                }
            }
         }

But the code never executes the inner block. “volumeIsRootFileSystem” should return a Bool so that I can check if the volume is local.

Any thoughts?

Thanks

It does return a boolean, so instead of checking for nil, check for false:

if networkVolume?.volumeIsRootFileSystem == false {

This works for me but gives my attached backup drive as well as a networked drive.

If you want to restrict the list to network drives only, you can use .volumeIsLocalKey and volumeIsLocal instead of .volumeIsRootFileSystemKey and volumeIsRootFileSystem.

This tutorial is more than six months old so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]