在外部编辑器中支持NSDocument更改?

Sam*_*fes 12 macos cocoa objective-c nsdocument

我有一个带有一些简单代码的NSDocument:

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
  self.string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  return YES;
}
Run Code Online (Sandbox Code Playgroud)

如果我在外部编辑器中更改文件,我如何得到通知,以便我可以处理它?我假设有一些内置的东西,但我找不到它.

我正在寻找内置于NSDocument中的东西.我知道FSEvent,但对于大多数基于文档的应用来说,这似乎太低了.

cti*_*tze 4

从 OS X v10.7 开始,NSDocument提供了一种更简单的机制,您可以在子类中重写:-presentedItemDidChange

处理-presentedItemDidChange、忽略元数据更改

但是,当元数据发生变化时,仅依赖此回调可能会产生误报。例如,对于存储在 Dropbox 中的文件,这很快就让我感到不安。

我在 Swift 中处理这个问题的一般方法是这样的:

class MyDocument: NSDocument {
    // ...

    var canonicalModificationDate: Date!

    override func presentedItemDidChange() {

        guard fileContentsDidChange() else { return }

        guard isDocumentEdited else {
            DispatchQueue.main.async { self.reloadFromFile() }
            return
        }

        DispatchQueue.main.async { self.showReloadDialog() }
    }

    fileprivate func showReloadDialog() {

        // present alert "do you want to replace your stuff?"
    }

    /// - returns: `true` if the contents did change, not just the metadata.
    fileprivate func fileContentsDidChange() -> Bool {

        guard let fileModificationDate = fileModificationDateOnDisk()
            else { return false }

        return fileModificationDate > canonicalModificationDate
    }

    fileprivate func fileModificationDateOnDisk() -> Date? {

        guard let fileURL = self.fileURL else { return nil }

        let fileManager = FileManager.default
        return fileManager.fileModificationDate(fileURL: fileURL)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你也必须更新canonicalModificationDate你的子类中的:

  • 在“您想替换内容吗?”的回调中 我称之为警报,-ignoreLatestFileChanges这样您就不会无休无止地打扰您的用户;
  • 不管怎样-readFromURL:ofType:error:,你最终会读入初始值的内容;
  • 不管怎样-dataOfType:error:,您都会生成要写入磁盘的内容。