Используя отмену в находящихся в AppKit приложениях

Набор Приложения дополняет поведение NSUndoManager несколькими способами:

Отмена и цепочка респондента

Приложение может иметь один или несколько клиентов отмены — возражает, что регистр и выполняет операции отмены в их локальных контекстах. Каждый из этих объектов имеет свое собственное NSUndoManager возразите и связанные стеки отмены и стеки повторного выполнения. Один пример этого сценария включает пользовательские представления, каждый клиент менеджера по отмене. Например, у Вас могло быть окно с двумя пользовательскими представлениями; каждое представление может вывести на экран текст в изменяемых атрибутах (таких как шрифт, цвет и размер), и пользователи могут отменить (или восстановление) каждое изменение в любом атрибуте в любом из представлений. NSResponder и NSWindow определите методы, чтобы помочь Вам управлять контекстом операций отмены в иерархии представления.

NSResponder объявляет undoManager метод для большинства объектов, наследовавшихся от него (а именно, окна и представления). Когда первый респондент приложения получает undo или redo сообщение, NSResponder восстанавливает работоспособность поиск цепочки респондента следующего респондента, возвращающегося NSUndoManager объект от undoManager. Любой возвращенный менеджер по отмене используется для работы восстановления или отмены.

Если undoManager сообщение направляется цепочку респондента к окну, NSWindow возразите запрашивает его делегатов с windowWillReturnUndoManager: видеть, есть ли у делегата менеджер по отмене. Если делегат не реализует этот метод, окно создает NSUndoManager объект для окна и всех его представлений.

Основанные на документе приложения часто делают их NSDocument возражает делегатам их окон, и сделайте, чтобы они ответили на windowWillReturnUndoManager: сообщение путем возврата менеджера по отмене используется для документа. Эти приложения могут также сделать каждого NSWindowController возразите делегату его окна — реализации контроллера окна windowWillReturnUndoManager: получить менеджера по отмене из ее документа и возвратить его:

return [[self document] undoManager];

NSTextView

Экземпляры NSTextView обеспечьте отмену и восстановите поведение. Это - дополнительная функция, и необходимо удостовериться, что, когда Вы создаете текст, просматривают, или Вы устанавливают надлежащий флажок в Интерфейсном Разработчике или отправляют его setAllowsUndo: с параметром YES. Если Вы хотите, чтобы текстовое представление использовало своего собственного менеджера по отмене (а не окно), Вы предоставляете делегату к текстовому представлению; делегат может тогда возвратить экземпляр NSUndoManager от undoManagerForTextView: метод делегата.

Поведение отмены и восстановления по умолчанию применяется к текстовым полям и тексту в ячейках пока поле, или ячейка является первым респондентом (т.е. фокус действий клавиатуры). Как только точка вставки покидает поле или ячейка, предшествующие операции не могут быть отменены.

Отмена и архитектура документа

При использовании архитектуры документа некоторые аспекты обработки отмены происходят автоматически. По умолчанию, каждый NSDocument объект имеет NSUndoManager объект. (Если Вы не хотите свое приложение, поддерживающее Отмену, можно использовать NSDocument метод setHasUndoManager: предотвратить создание менеджера по отмене.) Можно использовать setUndoManager: метод, если необходимо использовать подкласс или если иначе необходимо изменить менеджера по отмене, используемого документом.

Когда NSDocument объект имеет NSUndoManager объект, документ автоматически совершенствует свое отредактированное состояние путем наблюдения за уведомлениями от менеджера по отмене, говорящими его, когда изменения сделаны, отменены или восстановлены. В этом случае Вам никогда не придется вызывать NSDocument метод updateChangeCount: непосредственно, так как это вызывается автоматически в подходящее время.

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

Отмена и уровень модели

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

Часто полезно структурировать APIs Вашего объекта модели для строения из примитивных методов и расширенных методов. Примеры этого вида разделения могут быть найдены всюду по платформе Основы (включая NSString, NSArray, и NSDictionary) а также в проекте Эскиза в качестве примера. Если у Вас есть такое разделение в Ваших объектах модели, помните, что только примитивы должны зарегистрироваться для отмены с тех пор, по определению, расширенные методы реализованы с точки зрения примитивов.

Некоторые ситуации могли бы потребовать, чтобы Вы временно приостановили регистрацию отмены за определенные действия. Например, приложение Эскиза позволяет пользователю изменить размеры диаграммы путем захвата изменять размеры кнопки и перетаскивания его. Во время этого перетаскивания сотни или тысячи изменений могут быть сделаны к прямоугольнику границ выбранной диаграммы. Изменение границ диаграммы является примитивной работой и обычно приводило бы к регистрации отмены. В то время как пользователь активно изменяет размеры, тем не менее, было бы лучше, если бы не происходили те тысячи регистрации отмены. В этих случаях Ваш объект модели мог бы обеспечить API, чтобы временно временно отстранить и возобновить некоторых или всю его регистрацию отмены. Вам решать, чтобы решить, как обработать это. Конечно, это работало бы, если бы те тысячи регистрации отмены действительно происходили, но это была бы огромная трата памяти для запоминания всех тех промежуточных прямоугольников, когда Вы никогда не должны будете восстанавливать одно из тех промежуточных состояний.

Отмена и уровни управления и представления

Несмотря на то, что самая важная часть Вашей поддержки отмены должна быть в модели, существует две ситуации, где Вы нуждаетесь в некотором связанном с отменой коде или в Вашем контроллере или просматриваете объекты. Первый случай - когда Вы хотите, чтобы пункты меню Undo и Redo имели более определенные заголовки. Можно использовать NSUndoManager метод setActionName: дать имя к текущей группе отмены. Последний вызов setActionName: во время события цикл эффективный. Эти имена должны отразить намерение пользовательского действия, не примитивную работу, к которой приводит действие. Поэтому это находится в Ваших методах действия, что необходимо определить имена действия.

Не абсолютно необходимо назвать группу отмены. Пункты меню просто говорят «Отмену» и «Восстановление», не будучи определенными о том, что должно быть отменено или восстановлено. Но когда Вы действительно регистрируете имя, оно может помочь пользователю знать то, что будет отменено или восстановлено. Не слишком трудно опрыснуть несколько вызовов к setActionName: в Вашем представлении или сообщениях действия контроллера, таким образом, рекомендуется попытаться дать значимые имена действия.

Второй случай, где Вы могли бы иметь некоторый код отмены в контроллере или просмотреть уровни, - когда существуют некоторые вещи, изменяющиеся, которые не влияют на реальное положение документа, но который все еще должен быть невыполнимым. Отмена изменений выбора часто является таким случаем. Например, приложение Эскиза не могло бы полагать, что выбор был частью документа. Фактически, если документ может иметь многократные представления, открытые на нем, Вы могли бы быть в состоянии иметь различные выборы в каждом. Однако Вы могли бы хотеть, чтобы изменения в выборе были в состоянии быть отмененными для удобства пользователя и для визуальной непрерывности, когда пользователь фактически отменяет вещи. В этом случае представление, выводящее на экран графику, могло бы отслеживать выбор. Это должно зарегистрировать вызовы отмены, когда изменяется выбор.

Контроллер и объекты представления могут прийти и уйти во время времени жизни объекта документа, и это - рассмотрение, когда уровень контроллера или события уровня представления должны быть невыполнимыми. Вашим объектам модели, обычно живым для времени жизни документа и документа также, принадлежит менеджер по отмене, таким образом, Вы не должны обычно волноваться о том, что происходит, когда уходит модель. Но Вам, вероятно, придется волноваться о том, что происходит, когда уходят контроллер и объекты представления. Если Ваш объект контроллера или представления регистрирует какие-либо вызовы отмены, необходимо удостовериться, что они очищены от менеджера по отмене, когда освобождены контроллер или представление. Можно использовать NSUndoManager метод removeAllActionsWithTarget: с этой целью. Как только определенное представление о Вашем документе закрывается, нет никакого смысла в том, чтобы хранить информацию отмены о вещах, таких как изменения выбора для того представления.