I have a NSDocument
subclass that presents a text document from disk. I’m trying to make it refresh automatically on detecting file changes on disk. I’ve overridden -presentedItemDidChange
like this:
- (void)presentedItemDidChange
{
[super presentedItemDidChange];
// Ignoring bundles and error-handling for the moment.
NSData *newData = [NSData dataWithContentsOfURL:self.presentedItemURL];
self.textView.string = [[NSString alloc] initWithData:newData encoding:NSUTF8StringEncoding];
}
The UI refreshes fine when the file is changed in another application. The problem is, I get this dialog when I try to save the document in my application after it is modified by another app:
I kind of have an idea why this happens (not sure whether it’s correct): The modification time of the document is later (because it’s modified by another application) than the latest saved version in my app. But can I notify the autosaving system that I have done something with it and let it go away? Or am I doing things wrong when I refresh the document, and I should do it some other way to handle document versions correctly? I need to consider both external applications support or do not support autosave.
Thanks in advance.
@uranusjr's answer pointed me in the right direction -- only revertDocumentToSaved:
wasn't exactly the right place.
override func presentedItemDidChange() {
dispatch_async(dispatch_get_main_queue()) {
self.reloadFromFile()
}
}
func reloadFromFile() {
guard let fileURL = self.fileURL else { return }
do {
try revertToContentsOfURL(fileURL, ofType: "YOUR TYPE HERE IF NECESSARY")
} catch {
// TODO handle error
print(error)
}
}
This simply reloads the file. readFromURL(url:, ofType:)
(or the NSData/file wrapper based variants) is called and you can re-create your data structures from there.
Stumbled across the solution today (finally). You can “cheat” OS X into not warning about this by reverting the document (but not the file itself) before actually updating the internal data structure:
// Somehow read the updated data.
NSString *content = ...;
// Revert the document.
// This will discard any user input after the last document save,
// so you might want to present some UI here, like an NSAlert.
[self revertDocumentToSaved:self];
// Update the internal state.
self.content = content;
Now OS X will be happy when you save the document.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With