Можно ли использовать несколько NSUndoManager с одним Core-Data managedObjectContext? - PullRequest
11 голосов
/ 13 февраля 2011

// Редактировать: Действительно, никто не имеет никаких предложений или мыслей по этому поводу? Я задал вопрос как-то неправильно? //

В моем приложении для iPhone есть один управляемый объектный объект с умеренно сложной моделью данных. Сейчас я добавляю функции отмены, и не ясно, как лучше всего обрабатывать вложенные viewControllers (поскольку каждый слой может изменять модель данных).

Документы Apple указывают: «Рассмотрим приложение, которое отображает список книг, и позволяет перейти к подробному виду, который в свою очередь позволяет редактировать отдельные свойства книги (такие как ее название, автор и дата авторского права). Вы можете создать новую книгу из экран списка, перемещайтесь между двумя другие экраны для редактирования его свойств, затем вернитесь к оригиналу список. Это может показаться странным, если операция отмены в представлении списка изменение имени автора, которое было сделал два экрана, а не удаляя всю книгу. "


Так, каков наилучший способ реализовать это? В настоящее время я думаю, чтобы каждый viewController сохранял свой собственный undoManager, который будет активен, когда он находится на экране. Поэтому я понимаю, что для этого потребуются следующие шаги (для каждого VC):

  • Добавить объект: myUndoManager
  • Добавить undoManager метод, возвращающий myManagedObjectContext.undoManager;
  • In viewDidAppear: myManagedObjectContext.undoManager = myUndoManager; // создать первым, если nil
  • В viewWillDisappear: myManagedObjectContext.undoManager = nil;
  • Предупреждение о наличии памяти: [self.undoManager removeAllActions ];
  • На месте сделки: self.myUndoManager = nil;
  • Для каждого изменения модели: [self.undoManager setActionName:NSLocalizedString(@“XXX”,@“”)];
  • CoreData будет обрабатывать фактические сообщения отмены / повтора

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

  • В viewDidAppear: `[self intoFirstResponder] '
  • Добавить canBecomeFirstResponder метод, возвращающий ДА
  • В viewWillDisappear: [self resignFirstResponder];
  • Повторно включить firstResponder после отставки подпредставлений (например, textFields)

Пока что кажется, что это работает, даже при разных циклах загрузки / выгрузки, и прекрасно автономно, но у меня есть несколько вопросов:

  • Во-первых, является ли это наилучшей практикой для реализации отмены в нескольких VC?
  • Буду ли я иметь проблемы с моими детскими венчурными капиталистами, которые не делают их отмены до того, как я выполню свои предыдущие?
  • Если это так, захватывает ли этот список все, что мне нужно сделать?
  • Будет ли ManagedObjectContext перепутан с активностью нескольких UndoManager?
  • Нужно ли вызывать ProcessPendingActions перед заменой на undoManager?

Ответы [ 3 ]

1 голос
/ 27 апреля 2011

Я бы очень много работал, чтобы у меня был только один менеджер по отмене.
рассмотрим сценарий:

модель: (курица)
свойства: яйца, цвет, размер;

модель: (яйцо)
свойства: курица, цвет;

chicken.eggs = отношение «один ко многим» к яйцу, обратное верно для egg.chicken.

вы создаете 2 менеджера отмены, один для chickenViewController, а другой для eggViewController.
Вы создаете chicken0 и его яйца: egg0, egg1.
Вы создаете курицу1 и ее яйца: egg2, egg3.
Вы удаляете egg2.

теперь вы удаляете каскад chicken1, удаляя яйца.
теперь вы возвращаетесь к eggViewController и отменяете ... что вы хотите, чтобы произошло (исключение могло бы произойти).
теперь вы отменяете chickenViewController и chicken1, и его яйца возвращаются, но есть ли два egg2?

Редактировать Я немного смягчаю свой тон, Предполагая, что вы используете иерархическую структуру представления, такую ​​как UINavigationController, и вы создаете новый контроллер отмены каждый раз, когда переходите в дочернее представление, я не думаю, что у вас должна быть проблема.

0 голосов
/ 04 июня 2011

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

Допустим, у вас есть 3 уровня.Уровень 1 представляет всю запись, уровень 2 представляет подмножество данных уровня 1, а уровень 3 представляет подмножество данных уровня 2.

Как только вы вернулись с уровня 3, вы в основном сказали Я принимаю , и вам не нужно отменять какие-либо из этих данных на уровне 2. Эти измененные данные должны отображаться как данные только для чтения на уровне 2, если они вообще отображаются.Точно так же, как только вы вернетесь с уровня 2, вы должны освободить его менеджер отмены.

Назад на уровень 1, поскольку он представляет всю запись, почему бы не иметь кнопку Отмена вместо попытки отменить (или в дополнениев зависимости от того, что делает ваш контроллер уровня 1)?

Затем, если вы хотите отменить все операции, вы можете отправить следующее сообщение в контекст управляемого объекта:

[myMOC refreshObject:theEditedObject mergeChanges:NO];

Это эффективно откатит всю запись .

Если по какой-либо причине вы решите оставить менеджера отмены уровня 3, пока вы находитесь на уровне 2, и вы сделаете откат наНа уровне 2 будут откатываться только данные, относящиеся к менеджеру отмены уровня 2.Менеджер отмены уровня 3 является отдельным, и Базовые данные не видят менеджеров отмены как вложенные.

Контекст управляемого объекта не может быть перепутан из-за нескольких менеджеров отмены, потому что он может отслеживать только один за один раз черезего setUndoManager: метод.

Возможно, вам не нужно будет использовать processPendingChanges, если не произойдет откат до завершения цикла событий после внесения изменений.Я не стал бы беспокоиться об этом, если ваша отмена не восстановит только некоторые данные, которые должны быть записаны с помощью менеджера отмен до этого момента.

0 голосов
/ 02 апреля 2011

Звучит так, как будто вы хотите собрать кучу отмен в один кусок, чтобы они могли быть уничтожены как группа Это достигается с помощью beginUndoGrouping и endUndoGrouping. Есть ли какая-то причина, по которой вы не можете это использовать? Я не уверен, что вы можете отменить один шаг в середине группы, так что это будет проблемой.

...