arraysswiftnsfilemanagernsenumerator

Sorting arrays of file attributes by their creation date in Swift


I have been using Swift's [enumerator(at:includingPropertiesForKeys:options:)]1 to find all files within a given base path and create arrays for different resource keys (file name, path, creation date, etc). This has worked well, but I noticed that the elements in the created arrays are not ordered by their creation date, which is what I need before I pass the elements of these arrays into a loop to upload each file in their date order.

I therefore need to somehow sort the elements of all resulting arrays by their creation date, a property that I am able to extract within its own array (using the .creationDateKey resource key). I therefore have two options (I think):

  1. force elements to be first appended to the original arrays by their creation date
  2. sort the elements of each created array using the array containing file creation dates

What's the best way to do this? I thought it would be straightforward, but have not found it so.

All advice graciously received. Thanks.

Here is my code:

        // get URL(s) and other attributes of file(s) to be uploaded
        let localFileManager = FileManager()
        let resourceKeys = Set<URLResourceKey>([.nameKey, .pathKey, .creationDateKey, .isDirectoryKey])
        let directoryEnumerator = localFileManager.enumerator(at: baseURL, includingPropertiesForKeys: Array(resourceKeys), options: .skipsHiddenFiles)!
         
        var fileURLs: [URL] = []
        var fileNames: [String] = []
        var filePaths: [String] = []
        var fileDates: [Date] = []
        for case let fileURL as URL in directoryEnumerator {
            guard let resourceValues = try? fileURL.resourceValues(forKeys: resourceKeys),
                let isDirectory = resourceValues.isDirectory,
                let name = resourceValues.name,
                let path = resourceValues.path,
                let date = resourceValues.creationDate,
                else {
                    continue
            }
            if isDirectory {
                if name == "_extras" { // use this to exclude a given directory
                    directoryEnumerator.skipDescendants()
                }
            } else {
                
                // append elements in date order here?
                
                fileURLs.append(fileURL) // full URLs of files
                fileNames.append(name) // file names only
                filePaths.append(path) // paths of file
                fileDates.append(date) // date and time that file was created
                
                // sort arrays by creation date here?
                
            }
        }
        print(fileURLs)
        print(fileNames)
        print(filePaths)
        print(fileDates)

Solution

  • You should not use multiple arrays for this but instead wrap your values in a custom struct

    struct FileInfo {
        let url: URL
        let name: String
        let path: String //this is not really needed, you can get it from the url
        let date: Date
    }
    

    and have one array for this

    var files: [FileInfo]()
    

    and create your struct instance and append it

    files.append(FileInfo(url: fileURL, name: name, path: path, date: date)
    

    Sorting will now be trivial so after the for loop you do

    files.sort(by: { $0.date < $1.date })
    

    This sorts in ascending order, not sure which one you want.