Автосохранение не работает с NSUndoManager в UIManagedDocument

разрешение

NSUndoManager должен использоваться только в дочернем элементе NSManagedObjectContext (при использовании с Core Data). Это связано с тем, что UIManagedDocument может автоматически сохраняться в любой момент времени, после чего undo не будет иметь никакого эффекта. Поэтому нет смысла использовать NSUndoManager только для достижения функциональности сохранения/отмены, поскольку дочерний контекст даст вам тот же результат.

На самом деле немного грустно, потому что NSUndoManager намного проще реализовать, чем дочерний контекст (для последнего мне нужно вызвать existingObjectWithID, чтобы скопировать объекты из родителя в дочерний - болезненно). Лично я бы подумал, что документ не должен автоматически сохраняться, если groupingLevel != 0. Рэнт закончил.

Оригинальный вопрос

У меня есть контроллер табличного представления, который загружает данные с помощью Core Data в файл UIManagedDocument. Он переходит к контроллеру представления для редактирования каждой строки в таблице. В этом контроллере представления у меня есть кнопки отмены и сохранения. Я реализую возможность отмены, используя NSUndoManager через категорию моего объекта NSManaged (self.list ниже).

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.list beginEdit];
}

- (IBAction)cancel:(id)sender
{
    [self.list cancelEdit];
    [self close];
}

- (IBAction)save:(id)sender
{
    [self.list endEdit];
    [self close];
}

Категория реализует beginEdit, endEdit и cancelEdit, которые предназначены для обработки материала NSUndoManager. В приведенном ниже коде useUndo — это константа, для которой я установил значение NO или YES, чтобы увидеть влияние использования NSUndoManager.

- (void)beginEdit
{
    if (useUndo)
    {
        NSUndoManager *undoManager = [[NSUndoManager alloc] init];
        self.managedObjectContext.undoManager = undoManager;
        [undoManager beginUndoGrouping];
    }
}

- (void)endEdit
{
    [self.managedObjectContext save:nil];
    if (useUndo)
    {
        NSUndoManager *undoManager = self.managedObjectContext.undoManager;
        [undoManager endUndoGrouping];
        self.managedObjectContext.undoManager = nil;
    }
}

- (void)cancelEdit
{
    if (useUndo)
    {
        NSUndoManager *undoManager = self.managedObjectContext.undoManager;
        [undoManager endUndoGrouping];
        [undoManager undo];
    }
}

Я вижу отладочные сообщения Core Data, показывающие, что он фиксирует изменения, если я сохраняю объект и нажимаю кнопку «Домой», когда useUndo = NO. Однако с useUndo = YES он не сохраняется автоматически, когда я нажимаю кнопку «Домой». Я подождал пару минут, и он все еще не автосохраняется. Можно ли как-то принудительно выполнить автосохранение?

Кто-нибудь может объяснить, почему использование undoManager вызывает такое изменение поведения?

Я подозреваю, что либо я делаю это неправильно, либо у меня есть какая-то простая проблема в коде. Любая помощь будет оценена по достоинству.


person Michael    schedule 05.03.2013    source источник
comment
Прежде всего, никогда не вызывайте [self.managedObjectContext save:nil] (если это не childContext) при использовании UIManagedDocument. Вы всегда должны вызывать updateChangeCount: для своего объекта UIManagedDocument. См.: Использование контекста управляемого объекта управляемого документа   -  person Florian Mielke    schedule 19.04.2013


Ответы (1)


Я не уверен, правильно ли это, но в других ответах на stackoverflow упоминалось, что NSUndoManager очищает стек отмены при сохранении контекста. Это означает, что использование диспетчера отмены с автосохранением будет полезно максимум на пару секунд (независимо от интервала автосохранения). Может быть тут есть какая-то связь, я пытаюсь узнать больше...

person Andreas    schedule 09.08.2013
comment
Интересно - это соответствует другому поведению, которое я вижу, когда я начинаю группу отмены, вношу некоторые изменения, а затем выполняю отмену. Иногда между началом и отменой происходит автосохранение, поэтому отмена ничего не отменяет. Это менее чем бесполезно! Любое конкретное доказательство того, что такое поведение является преднамеренным, было бы полезно. Я не смог найти других ответов на NSUndoManager, очищающий стек отмены, или что-либо в документации Apple. - person Michael; 28.08.2013
comment
У меня есть еще информация. Управляемый документ автоматически сохраняет только два собственных контекста, поэтому вам придется создать свой собственный подконтекст, чтобы предотвратить автоматическое сохранение в неподходящее время. Затем сохраните контекст вручную. Тем не менее, я не думаю, что менеджер отмены должен управлять стеком отмены для ваших пользователей, только для ваших основных операций с данными. - person Andreas; 30.08.2013
comment
Для меня результатом является то, что если вы собираетесь использовать NSUndoManager, он должен быть в дочернем контексте. Следовательно, если требуется просто поддерживать сохранение/отмену, а не истинную отмену/повтор, нет смысла использовать NSUndoManager, поскольку это достигается либо сохранением, либо отбрасыванием дочернего контекста. Я отмечу ваш ответ как правильный. - person Michael; 04.09.2013