【问题标题】:NSFileManager watch directoryNSFileManager 监视目录
【发布时间】:2011-12-13 15:46:02
【问题描述】:

您将如何使用NSFileManager 监控目录?

我希望能够在我的应用程序运行时检测何时在我的文档目录中删除/添加了文件。

【问题讨论】:

标签: iphone ios xcode nsfilemanager


【解决方案1】:

这是我自己用 Swift 编写的 DirectoryWatcher 版本,使用 GCD 而不是 Mach,并使用闭包而不是委托

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")
})

销毁对象会停止观看,也可以显式停止

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];

【讨论】:

  • 应该认真考虑将其作为主要答案,因为原始答案尚未老化。尽管原始文档中的文档引用是正确的,但原始代码中引用的代码太旧了,几乎消失了(根据 cmets)。并且提到的博客文章实际使用了直接运行循环操作(在 Swift 时代有点陌生)。
  • 不错的解决方案,但不跟踪子文件夹
  • @kamyFC 确实如此,但我不知道有什么这样做的(Apple 的 DirectoryWatcher 没有,是吗?)
【解决方案2】:

在 Apple 文档中查看内核队列:文件系统事件的替代方案。 AVPlayerDemo 中有一个iOS 示例(请看DirectoryWatcher 类)。

另外,请查看 Directory Monitor 博文。

【讨论】:

猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 2013-02-07
  • 2010-12-13
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多