Forked from mattlawer/gist:3db21a1264afdca0314c7183143438bc
Last active
May 8, 2018 09:22
-
-
Save kirillrybin/cbd124d46b4f97e0dfd340d16a338d80 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