отменить все изменения, сделанные в контроллере дочернего представления

Есть две сущности: Автор и Книга. У автора есть атрибут authorName и отношения ко многим книгам. Книга имеет несколько атрибутов и авторские отношения. Существует контроллер представления (VCAuthor) для редактирования объекта Author. Контроллер дочернего представления (VCBook) предназначен для редактирования книг автора. Есть только один контекст управляемого объекта. В классе VCBook я группирую отладчик следующим образом

-(void)viewDidLoad
{    
    NSUndoManager *anUndoManager = [[NSUndoManager  alloc] init];
    [self.book.managedObjectContext setUndoManager:anUndoManager];
    [anUndoManager release];
    [self.book.managedObjectContext.undoManager beginUndoGrouping];
}

-(void)cancelAction:(id)sender
{
    NSLog(@"%@", self.author.authorName);
    [self.book.managedObjectContext.undoManager endUndoGrouping];
    [self.book.managedObjectContext.undoManager undoNestedGroup];
    self.book.managedObjectContext.undoManager = nil;
    NSLog(@"%@", self.author.authorName);    
    [self dismissModalViewControllerAnimated:YES];  
}

cancelAction связан с кнопкой отмены в VCBook, которая использовалась для отмены всех изменений, сделанных в VCBook.

Проблемы здесь: во-первых, в VCAuthor я редактирую authorName в UITextfiled authorNameTextField с Obama на Big Obama и сохраняю его в MOC по author.authorName = authorNameTextField.text в - (void) viewWillDisappear: (BOOL) анимированный {} метод. Затем я вошел в контроллер дочернего представления VCBook, чтобы отредактировать книги автора, и щелкнул кнопку отмены, чтобы вернуться к VCAuthor. Я считаю, что authorName по-прежнему Обама, это означает, что ожидаемое изменение authorName отменено. Смена authorName вообще не входит в группу отмены, и почему это могло произойти? пс. конечно, я перезагружаю данные, когда возвращаюсь в VCAuthor. Я просто веду журнал authorName до и после отмены. До отмены имя автора - это измененный Большой Обама, а после отмены - Обама.


person lu yuan    schedule 04.05.2012    source источник
comment
Я думаю, проблема здесь не в перезагрузке, проблема в том, что вы сохраняете измененное имя автора в сущности.   -  person Charan    schedule 04.05.2012
comment
но я не сгруппировал изменение, как его здесь можно было отменить?   -  person lu yuan    schedule 04.05.2012
comment
его поведение по умолчанию диспетчера отмены   -  person Charan    schedule 04.05.2012
comment
но я установил новый undoManager в VCBook.   -  person lu yuan    schedule 04.05.2012
comment
и если я нажму новый контроллер представления для редактирования authorName и сохраню измененное имя в сущности, когда вернусь к VCAuthor. Метод отмены в VCBook ни на что не повлияет.   -  person lu yuan    schedule 04.05.2012
comment
Это то, что я говорю, это не сохранение нового имени, отладьте его.   -  person Charan    schedule 04.05.2012
comment
Вы имеете в виду сохранить его в постоянном хранилище? Нет, я должен оставить действие сохранения для кнопки сохранения в VCAuthor. Сохранение в моем последнем комментарии принадлежит только author.authorName = authorNameTextField.text   -  person lu yuan    schedule 04.05.2012


Ответы (1)


Следует учесть несколько моментов. Во-первых, в подобном сценарии я бы использовал отдельный MOC вместо менеджера отмены. А именно, я бы сделал что-то вроде этого (при условии, что ARC - вы можете сделать сопоставление, если необходимо) ...

У вас должен быть какой-то другой код, предоставляющий книгу VC через сеттер, поскольку вы получаете доступ к нему в viewDidLoad. Я бы изменил viewDidLoad на что-то вроде этого ...

-(void)viewDidLoad
{
    self.managedObjectContext = [[NSManagedObjectContext alloc] init];
    self.managedObjectContext.parentContext = self.book.managedObjectContext;
    // We are in the main thread, so we can safely access the main MOC
    // Basically, move our object pointer to book into our local MOC.
    NSError * error = nil;
    Book *book = [self.managedObjectContext existingObjectWithID:self.book.objectID error:&error];
    // handle nil return and/or error
    self.book = book;
    // Now, your access to book will be in the local MOC, and any changes
    // you make to the book or book.author will all be confined to the local MOC.
}

Теперь все, что вам нужно сделать, это позвонить

[self.managedObjectContext save:&error];

в вашем действии saveAndDismiss. Если вы не вызываете save, ни одно из изменений не будет сохранено, все они просто автоматически исчезнут.

ИЗМЕНИТЬ

Обратите внимание, что указанное выше «сохранение» просто перемещает состояние объекта в родительский контекст. Итак, в «основном» MOC теперь есть изменения из «дочернего», но ни одно из изменений еще не было сохранено на диск.

person Jody Hagins    schedule 07.05.2012
comment
Если я использую отдельный MOC, книга не может быть добавлена ​​автору с помощью [self.author addBookObject self.book]; . Я не буду сохранять изменения в постоянном хранилище в VCBook. После завершения всех изменений в VCAuthor (таких как изменение имени автора, возраста и т. Д.), Они будут сохранены там. - person lu yuan; 08.05.2012
comment
Извините, но я не понимаю, что вы пытаетесь сказать в этом комментарии. Вы сделали три неполных заявления, и я не могу понять, какие проблемы вы пытаетесь описать. - person Jody Hagins; 08.05.2012
comment
Во-первых, если я редактирую книгу в отдельном MOC, я не могу добавить книгу автору с помощью [self.author addBookObject self.book] ;. Потому что они не в одном МОЦ. 2-й, в VCBook, [сохранение self.managedObjectContext: & error]; это не то, что я хочу по другим причинам. В-третьих, все изменения будут сохранены в постоянном хранилище при нажатии кнопки «Сохранить» в VCAuthor. - person lu yuan; 08.05.2012
comment
Вы читали код, который я опубликовал? Во-первых, у вас одновременно может быть активен только один контроллер представления. Этот конкретный контроллер представления, согласно тому, что вы сказали ранее, редактирует автора. Во-вторых, в плакате с кодом I текущий объект книги, который используется, находится в том же MOC. Наконец, ваши предположения ошибочны. Сохранение контекста автора просто помещает эти изменения в родительский MOC. Они не сохраняются, пока не сохранится MOC. - person Jody Hagins; 08.05.2012
comment
[сохранение self.managedObjectContext: & error]; этот код просто сохраняет изменения в parentContext, верно? позвольте мне попробовать позже, спасибо! - person lu yuan; 08.05.2012
comment
Кстати. Я не публиковал свое действие saveAndDismiss, о котором упоминалось в вашем ответе. - person lu yuan; 08.05.2012
comment
Правильно, сохранение дочернего контекста просто подталкивает эти изменения к родительскому контексту. Они не сохраняются в базе данных, пока их не сохранит корневой контекст. Кроме того, я просто создал saveAndDismiss, чтобы показать, что вам нужно сохранить контекст в родительском, когда это будет сделано ... и все потому, что если вы этого не сделаете, все изменения, сделанные в дочернем контексте, просто исчезнут, когда этот контекст освобожден. - person Jody Hagins; 08.05.2012
comment
Если сохранение не удалось, как вы можете отменить частичные неудачные изменения, если у вас нет диспетчера отмены? - person malhal; 23.12.2015
comment
Я бы спросил, как вы это делаете сейчас. Вы можете иметь менеджер отмены, но я считаю его ненужным и немного расточительным. Временный MOC действует как временный блокнот. Позвольте пользователю изменить данные во временном MOC или отказаться от всех изменений и начать все сначала. Опять же, это зависит от проблемы, которую вы пытаетесь решить ... Мне нужно было только один раз использовать диспетчер отмены для временного MOC. Ничего страшного, когда вы разрабатываете свое приложение для этих случаев использования. - person Jody Hagins; 24.12.2015