Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify library with DispatchSemaphore #17

Open
eonist opened this issue Oct 14, 2019 · 0 comments
Open

Simplify library with DispatchSemaphore #17

eonist opened this issue Oct 14, 2019 · 0 comments

Comments

@eonist
Copy link
Owner

eonist commented Oct 14, 2019

Observing changes in a file with DispatchSource
The final “lesser known” feature of GCD that I want to bring up is how it provides a way to observe changes in a file on the file system. Like DispatchSemaphore, this is something which can be super useful in a script or command line tool, if we want to automatically react to a file being edited by the user. This enables us to easily build developer tools that have “live editing” features.

Dispatch sources come in a few different variants, depending on what we want to observe. In this case we’ll use DispatchSourceFileSystemObject, which lets us observe events from the file system.

Let's take a look at an example implementation of a simple FileObserver, that lets us attach a closure to be run every time a given file is changed. It works by creating a dispatch source using a fileDescriptor and a DispatchQueue to perform the observation on, and uses Files to refer to the file to observe:

class FileObserver {
    private let file: File
    private let queue: DispatchQueue
    private var source: DispatchSourceFileSystemObject?

    init(file: File) {
        self.file = file
        self.queue = DispatchQueue(label: "com.myapp.fileObserving")
    }

    func start(closure: @escaping () -> Void) {
        // We can only convert an NSString into a file system representation
        let path = (file.path as NSString)
        let fileSystemRepresentation = path.fileSystemRepresentation

        // Obtain a descriptor from the file system
        let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY)

        // Create our dispatch source
        let source = DispatchSource.makeFileSystemObjectSource(
            fileDescriptor: fileDescriptor,
            eventMask: .write,
            queue: queue
        )

        // Assign the closure to it, and resume it to start observing
        source.setEventHandler(handler: closure)
        source.resume()
        self.source = source
    }
}
We can now use FileObserver like this:

let observer = try FileObserver(file: file)

observer.start {
    print("File was changed")
}

ref: https://www.swiftbysundell.com/articles/a-deep-dive-into-grand-central-dispatch-in-swift/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant