Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I suppress the autosave “The file has been changed by another application” alert?

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:

Alert when saving externally modified document

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.

like image 558
uranusjr Avatar asked Sep 12 '14 14:09

uranusjr


2 Answers

@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.

like image 124
ctietze Avatar answered Oct 19 '22 20:10

ctietze


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.

like image 1
uranusjr Avatar answered Oct 19 '22 19:10

uranusjr