-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
73 additions
and
0 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright © 2018 Schibsted. All rights reserved. | ||
|
||
import Foundation | ||
|
||
/// A basic wrapper around a VNODE dispatch source | ||
/// Every time the file is written to, a callback gets invoked | ||
class FileWatcher { | ||
private let _url: URL | ||
private let _event: DispatchSource.FileSystemEvent | ||
private let _queue: DispatchQueue | ||
|
||
private var _source: DispatchSourceFileSystemObject? | ||
|
||
public var fileChanged: (() -> Void)? { | ||
willSet { | ||
_source?.cancel() | ||
_source = nil | ||
} | ||
didSet { | ||
startObservingFileChangesIfPossible() | ||
} | ||
} | ||
|
||
init?(with url: URL, | ||
observing event: DispatchSource.FileSystemEvent = .write, | ||
queue: DispatchQueue = .global()) { | ||
_url = url | ||
_event = event | ||
_queue = queue | ||
|
||
guard fileExists() else { return nil } | ||
} | ||
|
||
deinit { | ||
_source?.cancel() | ||
} | ||
|
||
private func fileExists() -> Bool { | ||
return _url.isFileURL && FileManager.default.fileExists(atPath: _url.path) | ||
} | ||
|
||
private func startObservingFileChangesIfPossible() { | ||
guard fileExists() else { return } | ||
guard fileChanged != nil else { return } | ||
|
||
let descriptor = open(_url.path, O_EVTONLY) | ||
|
||
guard descriptor > 0 else { return } | ||
|
||
let source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: descriptor, eventMask: _event, queue: _queue) | ||
_source = source | ||
|
||
source.setEventHandler { [weak self] in self?.fileChanged?() } | ||
|
||
source.setCancelHandler() { close(descriptor) } | ||
|
||
source.resume() | ||
} | ||
} |