Created
September 18, 2016 17:28
-
-
Save mattlawer/3db21a1264afdca0314c7183143438bc to your computer and use it in GitHub Desktop.
DirectoryMonitor - Swift 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2016 Apple Inc. All Rights Reserved. | |
See LICENSE.txt for this sample’s licensing information | |
Abstract: | |
`DirectoryMonitor` is used to monitor the contents of the provided directory by using a GCD dispatch source. | |
*/ | |
import Foundation | |
/// A protocol that allows delegates of `DirectoryMonitor` to respond to changes in a directory. | |
protocol DirectoryMonitorDelegate: class { | |
func directoryMonitorDidObserveChange(_ directoryMonitor: DirectoryMonitor) | |
} | |
class DirectoryMonitor { | |
// MARK: Properties | |
/// The `DirectoryMonitor`'s delegate who is responsible for responding to `DirectoryMonitor` updates. | |
weak var delegate: DirectoryMonitorDelegate? | |
/// A file descriptor for the monitored directory. | |
var monitoredDirectoryFileDescriptor: CInt = -1 | |
/// A dispatch queue used for sending file changes in the directory. | |
let directoryMonitorQueue = DispatchQueue(label: "com.example.apple-samplecode.lister.directorymonitor", attributes: .concurrent) | |
/// A dispatch source to monitor a file descriptor created from the directory. | |
var directoryMonitorSource: DispatchSourceFileSystemObject? | |
/// URL for the directory being monitored. | |
var url: URL | |
// MARK: Initializers | |
init(URL: URL) { | |
self.url = URL | |
} | |
// MARK: Monitoring | |
func startMonitoring() { | |
// Listen for changes to the directory (if we are not already). | |
if directoryMonitorSource == nil && monitoredDirectoryFileDescriptor == -1 { | |
// Open the directory referenced by URL for monitoring only. | |
monitoredDirectoryFileDescriptor = open(url.path, O_EVTONLY) | |
// Define a dispatch source monitoring the directory for additions, deletions, and renamings. | |
directoryMonitorSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: monitoredDirectoryFileDescriptor, eventMask: [.write, .delete], queue: directoryMonitorQueue) | |
// Define the block to call when a file change is detected. | |
directoryMonitorSource?.setEventHandler(handler: { | |
// Call out to the `DirectoryMonitorDelegate` so that it can react appropriately to the change. | |
self.delegate?.directoryMonitorDidObserveChange(self) | |
}) | |
// Define a cancel handler to ensure the directory is closed when the source is cancelled. | |
directoryMonitorSource?.setCancelHandler(handler: { | |
close(self.monitoredDirectoryFileDescriptor) | |
self.monitoredDirectoryFileDescriptor = -1 | |
self.directoryMonitorSource = nil | |
}) | |
// Start monitoring the directory via the source. | |
directoryMonitorSource?.resume() | |
} | |
} | |
func stopMonitoring() { | |
// Stop listening for changes to the directory, if the source has been created. | |
if directoryMonitorSource != nil { | |
// Stop monitoring the directory via the source. | |
directoryMonitorSource?.cancel() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @mattlawer!
Does not work when a file on the path is updated? I trying to figure out how this works and it fires a notification when I create or remove a file but not when I update the file. Btw I tried changing "[.write, .delete]"to ".all" and it did not worked.