Search code examples
nsfilemanagerswift3haneke

What's the Swift 3 enumerateContentsOfDirectoryAtPath Syntax? (Haneke)


I'm converting the Haneke Cacheing framework to Swift 3 and I've run into a snag with enumerateContentsOfDirectoryAtPath.

Here's the original syntax (view on github),

let fileManager = NSFileManager.defaultManager()
let cachePath = self.path

fileManager.enumerateContentsOfDirectoryAtPath(cachePath, orderedByProperty: NSURLContentModificationDateKey, ascending: true) { (URL : NSURL, _, inout stop : Bool) -> Void in                
    if let path = URL.path {
        self.removeFileAtPath(path) 
        stop = self.size <= self.capacity
    }
}

I believe what I'm looking for is the following function which I found by looking at the FileManger definition, however I don't know how to make the conversion:

public func enumerator(atPath path: String) -> FileManager.DirectoryEnumerator?

Question

What's the Swift 3 equivalent of enumerateContentsOfDirectoryAtPath and how should I use it while converting the above example?


Solution

  • enumerateContensOfDirectoryAtPath is an extension defined by the Haneke framework available here. It's not a standard method for NSFileManager. You need to translate that extension to Swift 3 first:

    extension FileManager {
    
        func enumerateContentsOfDirectoryAtPath(_ path: String, orderedByProperty property: URLResourceKey, ascending: Bool, usingBlock block: (URL, Int, inout Bool) -> Void ) {
    
            let directoryURL = URL(fileURLWithPath: path)
            do {
                let contents = try self.contentsOfDirectory(at: directoryURL, includingPropertiesForKeys: [property.rawValue], options: FileManager.DirectoryEnumerationOptions())
                let sortedContents = contents.sorted(isOrderedBefore: {(URL1: URL, URL2: URL) -> Bool in
    
                    // Maybe there's a better way to do this. See: http://stackoverflow.com/questions/25502914/comparing-anyobject-in-swift
    
                    var value1 : AnyObject?
                    do {
                        try (URL1 as NSURL).getResourceValue(&value1, forKey: property);
                    } catch {
                        return true
                    }
                    var value2 : AnyObject?
                    do {
                        try (URL2 as NSURL).getResourceValue(&value2, forKey: property);
                    } catch {
                        return false
                    }
    
                    if let string1 = value1 as? String, let string2 = value2 as? String {
                        return ascending ? string1 < string2 : string2 < string1
                    }
    
                    if let date1 = value1 as? Date, let date2 = value2 as? Date {
                        return ascending ? date1 < date2 : date2 < date1
                    }
    
                    if let number1 = value1 as? NSNumber, let number2 = value2 as? NSNumber {
                        return ascending ? number1 < number2 : number2 < number1
                    }
    
                    return false
                })
    
                for (i, v) in sortedContents.enumerated() {
                    var stop : Bool = false
                    block(v, i, &stop)
                    if stop { break }
                }
    
            } catch {
                Log.error("Failed to list directory", error as NSError)
            }
        }
    
    }
    
    func < (lhs: Date, rhs: Date) -> Bool {
        return lhs.compare(rhs) == ComparisonResult.orderedAscending
    }
    
    func < (lhs: NSNumber, rhs: NSNumber) -> Bool {
        return lhs.compare(rhs) == ComparisonResult.orderedAscending
    }
    

    Usage:

    let fileManager = FileManager.default
    let cachePath = self.path
    
    fileManager.enumerateContentsOfDirectoryAtPath(cachePath, orderedByProperty: URLResourceKey.contentModificationDateKey, ascending: true) { (url, _, stop: inout Bool) in
        // ...
    }