Swift / Cocoa: How to watch folder for changes?

4.5k views Asked by At

I'm writing a small macOS app, where I want to be able to watch a folder for changes. It doesn't need to watch subfolder, I only want to receive a notification if a file is added to the folder or removed.

It looks like NSFileCoordinator and/or NSFilePresenter could be used to achieve this, but I was not able to understand how to use them to achieve this.

Ideally this can be solved without having to include a third party framework.

2

There are 2 answers

5
Marc T. On BEST ANSWER

You can do this using NSFilePresenter. The observing class must conform to NSFilePresenter as shown below.

The presentedItemURL would point to the folder you want to observe. If there is a change in the folder presentedSubitemDidChangeAtURL get called. The code snipped below could give you an idea how it can work.

class ObservingClass: NSObject, NSFilePresenter {

    lazy var presentedItemOperationQueue = NSOperationQueue.mainQueue()
    var presentedItemURL:NSURL?
    

    func presentedSubitemDidChangeAtURL(url: NSURL) {
        let pathExtension = url.pathExtension    
        if pathExtension == "png"{
            refreshImages()
        }
    }

   func refreshImages(){
        let path = snapshotPath
        var isDirectory: ObjCBool = ObjCBool(false)
        
        if NSFileManager.defaultManager().fileExistsAtPath(path!, isDirectory: &isDirectory){
            if isDirectory{
                do {
                    let list = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(path!) as Array<String>
                    for filePath in list {
                        if filePath.hasSuffix(".png"){
                            if let snapshot = snapshotAtPath(path! + "/" + filePath){
                                newSnapshotArray += [snapshot]
                            }
                        }
                    }
                } catch {
                    // error handling 
                }
            }
        }
    }
}

Best wishes.

0
Paul On

Marc T's answer still works and seems to be the easiest solution for this.

To make it work I needed to add the following line (could be at the init() of ObservingClass):

NSFileCoordinator.addFilePresenter(self)