Search code examples
swiftcocoacore-datansdocument

Undo troubles: Initialise `NSPersistentDocument` programmatically without "edited" flag in title bar


I have a small app using core data and NSPersistentDocument. For new documents I initialize the document with a single Settings element. I already could suppress the undo entry generated by the initialization, but...

The strange behaviour is this: The document starts with no "edited" flag in the window title. As soon as I click into the "Edit" menu, the "edited" flag appears and there is suddenly a undo action possible.

Here my init() code:

class Document: NSPersistentDocument {
    var settings: Settings! = nil
    override init() {
        super.init()
        do {
            let fetchSettings = NSFetchRequest(entityName: "Settings")
            let settingsList = try self.managedObjectContext!.executeFetchRequest(fetchSettings)
            precondition(settingsList.count < 2, "Too many settings object in the core data store.")
            if settingsList.count == 1 {
                settings = settingsList[0] as? Settings
                precondition(settings != nil)
            } else {
                managedObjectContext!.undoManager!.disableUndoRegistration()
                settings = NSEntityDescription.insertNewObjectForEntityForName("Settings", inManagedObjectContext: self.managedObjectContext!) as? Settings
                precondition(settings != nil)
                // Here setup the "settings" object...
                settings.xxx = //...
                settings.yyy = //...
                managedObjectContext!.undoManager!.enableUndoRegistration()
            }
        } catch {
            preconditionFailure("Could not retrieve/create settings object because of an unknown core data error.")
        }
    }
    // ... more methods ...
}

The problem is, as soon this undo entry appears, the user can undo the creation of the initial Settings object which causes many troubles.

Is this a known problem? How can I prevent this from happen?

Here a video which demonstrates the effect: https://youtu.be/O4lURxLAelE


Solution

  • Call

    [self.managedObjectContext processPendingChanges];
    

    before disableUndoRegistration and enableUndoRegistration.