繁体   English   中英

在没有 fsevent 的情况下监视 OSX 中目录的更改

[英]Monitoring a directory for changes in OSX without fsevent

是否有 fsevent 的替代品或某种包装器?

我正在尝试监视特定文件夹以更改具有特定扩展名的文件。

UKKQueue是一个不错的包装,用于内核队列事件监视-文档中提到的替代方法。

如今,您可以使用 GCD 来监控文件夹,而无需任何其他依赖项:

import Foundation

@objc public class DirectoryWatcher : NSObject {
    override public init() {
        super.init()
    }
    
    deinit {
        stop()
    }
    
    public typealias Callback = (_ directoryWatcher: DirectoryWatcher) -> Void
    
    @objc public convenience init(withPath path: String, callback: @escaping Callback) {
        self.init()
        if !watch(path: path, callback: callback) {
            assert(false)
        }
    }
    
    private var dirFD : Int32 = -1 {
        didSet {
            if oldValue != -1 {
                close(oldValue)
            }
        }
    }
    private var dispatchSource : DispatchSourceFileSystemObject?
    
    @objc public func watch(path: String, callback: @escaping Callback) -> Bool {
        // Open the directory
        dirFD = open(path, O_EVTONLY)
        if dirFD < 0 {
            return false
        }
        
        // Create and configure a DispatchSource to monitor it
        let dispatchSource = DispatchSource.makeFileSystemObjectSource(fileDescriptor: dirFD, eventMask: .write, queue: DispatchQueue.main)
        dispatchSource.setEventHandler {[unowned self] in
            callback(self)
        }
        dispatchSource.setCancelHandler {[unowned self] in
            self.dirFD = -1
        }
        self.dispatchSource = dispatchSource

        // Start monitoring
        dispatchSource.resume()
        
        // Success
        return true
    }

    @objc public func stop() {
        // Leave if not monitoring
        guard let dispatchSource = dispatchSource else {
            return
        }
        
        // Don't listen to more events
        dispatchSource.setEventHandler(handler: nil)
        
        // Cancel the source (this will also close the directory)
        dispatchSource.cancel()
        self.dispatchSource = nil
    }
}

像 Apple 的 DirectoryWatcher 示例一样使用它,如下所示:

let directoryWatcher = DirectoryWatcher(withPath: "/path/to/the/folder/you/want/to/monitor/", callback: {
    print("the folder changed")
})

销毁 object 将停止观看,或者您可以显式停止它

directoryWatcher.stop()

它应该与 Objective C 兼容(未测试)。 使用它会是这样的:

DirectoryWatcher *directoryWatcher = [DirectoryWatcher.alloc initWithPath: @"/path/to/the/folder/you/want/to/monitor/" callback: ^(DirectoryWatcher *directoryWatcher) {
    NSLog(@"the folder changed")
}];

停止它是相似的

[directoryWatcher stop];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM