Редактирование текста
В этой главе описываются пути, которыми можно управлять поведением текстовой системы Какао, поскольку это выполняет редактирование текста. Редактирование текста является модификацией текстовых символов или атрибутов путем взаимодействия с текстовыми объектами. Обычно, редактирование выполняется прямым пользовательским действием с текстовым представлением, но это может также быть выполнено программируемым взаимодействием с текстовым объектом хранения. Этот документ также обсуждает систему ввода текста, переводящую события клавиатуры в команды и ввод текста.
Текстовая система Какао реализует сложный механизм редактирования, включающий ввод и модификацию сложного текстового символа и информации о стилях. Важно понять этот механизм, если Ваш код должен сцепиться в него для изменения того поведения.
Текстовая система обеспечивает много контрольных точек, где можно настроить поведение редактирования:
Текстовые системные классы обеспечивают методы для управления многими путями, которыми они выполняют редактирование.
Можно реализовать больше управления через механизмы Какао уведомления и делегации.
В крайних случаях, где возможности текстовой системы не подходят, можно заменить текстовое представление пользовательским подклассом.
Среда редактирования
Редактирование текста выполняется текстовым объектом представления. Как правило, текстовое представление является экземпляром NSTextView
или подкласс. Текстовое представление обеспечивает фронтэнд для текстовой системы. Это выводит на экран текст, обрабатывает пользовательские события, редактирующие текст и изменения координат в сохраненном тексте, требуемом процессом редактирования. NSTextView
методы реализаций, выполняющие редактирование, управляют выбором и обрабатывают атрибуты форматирования, влияющие на расположение и дисплей текста.
NSTextView
имеет много методов, управляющих поведением редактирования, доступным пользователю. Например, NSTextView
позволяет Вам предоставлять или отклонять пользователя возможность выбрать или отредактировать ее текст, с помощью setSelectable:
и setEditable:
методы. NSTextView
также реализует различие между простым и обогащенным текстом, определенным NSText
с setRichText:
и setImportsGraphics:
методы. См. текстовое Руководство по программированию Уровня Интерфейса Пользователя системы, Ссылку класса NSTextView и Ссылку класса NSText для получения дополнительной информации.
Доступное для редактирования текстовое представление может работать в любом из двух отличных режимов редактирования: как редактор обычного текста или как полевой редактор. Полевой редактор является единственным текстовым экземпляром представления, совместно использованным многими текстовыми полями, принадлежащими окну в приложении. Это совместное использование приводит к увеличению производительности. Когда текстовое поле становится первым респондентом, окно вводит полевого редактора в свое место в цепочке респондента. Редактор обычного текста принимает символы Tab и Return как ввод, тогда как полевой редактор интерпретирует Вкладку и Возврат как сигналы для окончания редактирования. NSTextView
метод setFieldEditor:
средства управления это поведение.
Посмотрите Работу с Полевым Редактором для получения дополнительной информации о полевом редакторе.
Последовательность Ключевого Входного сигнала
Когда Вы хотите изменить путь, которым Какао редактирует текст, полезно понять последовательность сообщений, определяющую механизм редактирования, таким образом, можно выбрать самую надлежащую точку, в которой можно добавить пользовательское поведение.
Последовательность сообщений, вызванная, когда текстовое представление получает ключевые события, включает четыре метода, объявленные NSResponder
. Когда пользователь нажимает клавишу, операционная система обрабатывает определенные зарезервированные ключевые события и отправляет других в NSApplication
объект, обрабатывающий события Командной клавиши как ключевые эквиваленты. Ключевые события, не обработанные, отправляются объектом приложения в ключевое окно, обрабатывающее ключевые события, отображенные на действиях перемещения с помощью клавиатуры (таких как внимание перемещения Вкладки на следующее представление), и отправляющее другие ключевые события первому респонденту. Рисунок 7-1 иллюстрирует эту последовательность.
Если первый респондент является текстовым представлением, ключевое событие вводит текстовую систему. Ключевое окно отправляет текстовое представление a keyDown:
сообщение с событием как его параметр. keyDown:
метод передает событие handleEvent:
, который отправляет ввод символов во входной контекст для привязки клавиш и интерпретации. В ответ входной контекст отправляет также insertText:replacementRange:
, setMarkedText:selectedRange:replacementRange:
, или doCommandBySelector:
к текстовому представлению. Рисунок 7-2 иллюстрирует последовательность обработки событий ввода текста.
Система ввода текста использует список свойств словаря, названный словарем привязок клавиш, для интерпретации событий клавиатуры прежде, чем передать их платформе Набора Метода ввода для отображения на символы.
Во время обработки события клавиатуры событие проходит NSMenu
объект, затем первому респонденту через keyDown:
метод. Реализация по умолчанию метода, предоставленного NSResponder
класс распространяет сообщение цепочка респондента до переопределенного keyDown:
реализация останавливает распространение. Как правило, NSResponder
подкласс может принять решение обработать определенные ключи и проигнорировать других (например, в игре) или отправить handleEvent:
обменивайтесь сообщениями к его входному контексту.
Входной контекст проверяет событие, чтобы видеть, соответствует ли это какие-либо из нажатий клавиш в словаре привязок клавиш пользователя. Словарь привязок клавиш отображает нажатие клавиши (включая его модифицирующие клавиши) к имени метода. Например, карты словаря привязок клавиш по умолчанию ^d
(Управление-D) к имени метода deleteForward:
. Если событие клавиатуры находится в словаре, то входной контекст вызывает текстовое представление doCommandBySelector:
метод с селектором связался со словарной статьей.
Если входной контекст не может соответствовать событие клавиатуры к записи в словаре привязок клавиш, это передает событие Набору Метода ввода для отображения на символы.
Стандартный словарь привязок клавиш находится в файле /System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict
. Можно переопределить стандартный словарь полностью путем обеспечения файла словаря в пути ~/Library/KeyBindings/DefaultKeyBinding.dict
. Однако определение пользовательских привязок клавиш динамично (т.е. в то время как приложение работает) не поддерживается.
Для получения дополнительной информации об обработке ключевого события ввода текста, см. “текстовые Системные значения по умолчанию и Привязки клавиш” в Руководстве по Обработке событий Какао.
Когда текстовое представление имеет достаточно информации для указания фактического изменения в его тексте, это отправляет сообщение редактирования в его NSTextStorage
объект вызвать изменение. Методы, изменяющие символ и информацию атрибута в текстовом объекте хранения, объявляются в NSTextStorage
суперкласс NSMutableAttributedString
, и они зависят от двух примитивных методов replaceCharactersInRange:withString:
и setAttributes:range:
. Текстовый объект хранения тогда сообщает своим менеджерам по расположению изменения для инициирования генерации глифа и расположения при необходимости, и это отправляет уведомления и отправляет сообщения делегата прежде и после обработки редактирований. Для получения дополнительной информации о взаимодействии текстового представления, текстовое хранение и менеджер по расположению объекты, видят текстовое Руководство по программированию Расположения.
Прерывание ключевых событий
Этот раздел объясняет, как поймать ключевые события, полученные текстовым представлением так, чтобы можно было изменить результат. Это также объясняет последовательность сообщений, происходящую, когда текстовое представление получает ключевое событие.
Необходимо прервать ключевые события, например, если Вы хотите, чтобы пользователи были в состоянии вставить символ разрыва строки в текстовое поле. По умолчанию текстовые поля содержат только одну строку текста. Нажатие Enter или Return заставляет текстовое поле заканчивать редактирование и отправлять его сообщение действия в его цель, таким образом, необходимо было бы изменить поведение.
Можно также хотеть прервать ключевые события в текстовом представлении, чтобы сделать что-то другое от простого ввода символов в тексте, выводимом на экран представлением, таких как изменение содержания в буфере памяти.
При обоих обстоятельствах необходимо иметь дело с текстовым объектом представления, который очевиден для текстового случая представления, но меньше для текстового поля. Редактирование в текстовом поле выполняется NSTextView
объект, названный полевым редактором, совместно использованным всеми текстовыми полями, принадлежащими окну.
Когда текстовое представление получает ключевое событие, оно отправляет ввод символов во входной контекст для привязки клавиш и интерпретации. В ответ входной контекст отправляет также insertText:replacementRange:
или doCommandBySelector:
к текстовому представлению, в зависимости от того, представляет ли ключевое событие текст, который будет вставлен или команда для выполнения. Входной контекст может также отправить setMarkedText:selectedRange:replacementRange:
обменивайтесь сообщениями для установки отмеченного текста в связанном текстовом объекте хранения представления текста. Последовательность сообщений, вызванная, когда текстовое представление получает ключевые события, описана более подробно в Последовательности Ключевого Входного сигнала.
Со стандартными привязками клавиш символ Enter или Return заставляет текстовое представление получать doCommandBySelector:
с селектором insertNewline:
, который может иметь один из двух результатов. Если текстовое представление не является полевым редактором, текстовое представление insertText:replacementRange:
метод вставляет символ разрыва строки. Если текстовое представление является полевым редактором, как тогда, когда пользователь редактирует текстовое поле, текстовые концы представления, редактирующие вместо этого. Можно заставить текстовое представление вести себя в так или иначе путем вызова setFieldEditor:
.
Несмотря на то, что Вы могли изменить текстовое поведение представления путем разделения на подклассы текстового представления и переопределения insertText:replacementRange:
и doCommandBySelector:
, лучшее решение состоит в том, чтобы обработать событие в текстовом делегате представления. Делегат может взять на себя управление над пользовательскими изменениями в тексте путем реализации textView:shouldChangeTextInRange:replacementString:
метод.
Для обработки нажатий клавиш, не вставляющих текст делегат может реализовать textView:doCommandBySelector:
метод.
Для различения Входят и Возврат, например, делегат может протестировать селектор, переданный с doCommandBySelector:
. Если это @selector(insertNewline:)
, можно отправить currentEvent
к NSApp
объект удостовериться событие является ключевым событием и, если так, какая клавиша была нажата.
Текстовая делегация представления
Делегация обеспечивает мощный механизм для изменения поведения редактирования, потому что можно реализовать методы в делегате, который может тогда выполнить команды редактирования вместо текстового представления, метод вызвал делегацию реализации. NSTextView
дает его делегату эту возможность обработать команду путем отправки ему a textView:doCommandBySelector:
обменивайтесь сообщениями каждый раз, когда это получает a doCommandBySelector:
сообщение от входного контекста. Если делегат реализует этот метод и возвраты YES
, текстовое представление ничего не делает далее; если возвращается делегат NO
, текстовое представление должно попытаться выполнить саму команду.
Прежде чем текстовое представление вносит любое изменение в свой текст, это отправляет своего делегата a textView:shouldChangeTextInRange:replacementString:
сообщение, возвращающее булево значение. (Как со всеми сообщениями делегата, это отправляет сообщение, только если делегат реализует метод.) Этот механизм предоставляет делегату возможность управлять всем редактированием символа и данных атрибута в текстовом объекте хранения, связанном с текстовым представлением.
Текстовый делегат представления обменивается сообщениями и уведомления
NSTextView
объект может иметь делегата, которому он сообщает об определенных действиях или незаконченных изменениях в состоянии текста. Делегат может быть любым объектом, который Вы выбираете, и один делегат может управлять многократный NSTextView
объекты (или многократная серия связанных NSTextView
объекты). Рисунок 7-3 иллюстрирует действие делегата NSTextView
объект, получающий сообщение делегата textView:shouldChangeTextInRange:replacementString:
.
Ссылка на протокол NSTextDelegate и Ссылка на протокол NSTextViewDelegate описывают сообщения делегата, которые может получить делегат. Объект делегирования отправляет сообщение, только если делегат реализует метод.
Все NSTextView
объекты, присоединенные к тому же NSLayoutManager
совместно используйте того же делегата. Установка делегата одного такого текстового представления устанавливает делегата ко всему другие. Делегат передает передачу id
из отправителя как параметр.
Уведомления, отправленные NSTextView
:
Для наблюдателей особенно важно зарегистрироваться для последнего из этих уведомлений. Если новое NSTextView
объект добавляется в начале серии связанных NSTextView
объекты, это становится новым текстовым представлением уведомления. Это не имеет доступа, к которому объекты наблюдают его группу текстовых объектов, таким образом, это отправляет NSTextViewWillChangeNotifyingTextViewNotification
, который позволяет всем тем наблюдателям не регистрировать себя от старого текстового представления уведомления и повторно регистрировать себя в новом. Для получения дополнительной информации см. описание для этого уведомления в Ссылке класса NSTextView.
Делегация текстового поля
Текстовые поля (т.е. экземпляры NSTextField
, в противоположность экземплярам NSTextView
) может также использовать делегацию для управления их поведением редактирования. Один путь, которым это сделано, для самого текстового поля для обозначения делегата. Как правило, Вы делаете это в Интерфейсном Разработчике Перетаскиванием управления от объекта текстового поля до объекта делегата, но можно также сделать это во время выполнения путем отправки текстового поля a setDelegate:
сообщение, например, в awakeFromNib
метод. Делегат должен реагировать на сообщения, определенные NSTextFieldDelegate
протокол (который принимает NSControlTextEditingDelegate
протокол). В дополнение к методам, определенным NSControlTextEditingDelegate
протокол, делегат текстового поля может реагировать на методы делегата NSControl
.
Как пример того, как делегат текстового поля может управлять его поведением редактирования, можно отключить текстовое завершение в текстовом поле при наличии его реализации делегата метод делегата control:textView:completions:forPartialWordRange:indexOfSelectedItem:
просто возвратиться nil
.
Иначе, в котором можно настроить поведение редактирования в текстовом поле делегацией, вовлекает полевого редактора, NSTextView
возразите, что обрабатывает фактическое редактирование, в свою очередь, для всех текстовых полей в окне. Полевой редактор автоматически определяет любое текстовое поле, которое это редактирует как его делегат, таким образом, можно инкапсулировать специальное поведение редактирования для текстового поля с самим текстовым полем путем реализации методов делегата, определенных NSTextDelegate
и NSTextViewDelegate
протоколы. Для получения информации об управлении поведением редактирования текстовых полей через сообщения делегата и уведомления, отправленные полевым редактором, посмотрите Используя Делегацию и Уведомление с Полевым Редактором.
Синхронизация редактирования
Процесс редактирования включает тщательную синхронизацию сложного взаимодействия различных объектов. Текстовая система координирует обработку событий, модификацию данных, управление цепочкой респондента, генерацию глифа и расположение для поддержания непротиворечивости в текстовой модели данных.
Система обеспечивает богатый набор уведомлений делегатам и наблюдателям, чтобы позволить Вашему коду взаимодействовать с этой логикой, как описано в текстовом Делегате Представления сообщения и Уведомления.
Пакетный режим редактирования
Если Ваш код должен изменить текстовое запоминающее устройство непосредственно, необходимо использовать пакетный режим редактирования; т.е. заключите в скобки изменения между NSMutableAttributedString
методы beginEditing
и endEditing
. Несмотря на то, что это заключение в скобки не строго необходимо, это - хорошая практика, и для эффективности при внесении многократных изменений по очереди важно. NSTextView
использование beginEditing
и endEditing
методы для синхронизации его действия редактирования, и можно использовать методы непосредственно для управления синхронизацией уведомлений делегатам, наблюдателям и связанным менеджерам по расположению. Когда NSTextStorage
объект находится в пакетном режиме редактирования, он воздерживается от информирования его менеджеров по расположению любых изменений редактирования, пока он не получает endEditing
сообщение.
“Начало редактирования” означает что ряд модификаций к текстовому запоминающему устройству (NSTextStorage
для текстовых представлений и значений ячеек для ячеек), собирается произойти. Заключение в скобки редактирования между beginEditing
и endEditing
блокировки вниз текстовое хранение, чтобы гарантировать, что текстовые модификации являются атомарными транзакциями.
“Конец редактирования” означает, что запоминающее устройство находится в непротиворечивом состоянии после модификации. В ячейках (такой как NSTextFieldCell
объекты, управляющие редактированием текста в текстовых полях), конец редактирования совпадает с полевым редактором, оставляющим первое состояние респондента, инициировавшее синхронизацию содержания полевого редактора и его родительской ячейки.
Кроме того, текстовое представление отправляет NSTextDidEndEditingNotification
когда это завершает изменение его запоминающего устройства, независимо от его первого состояния респондента. Например, это отсылает это уведомление, когда кнопка Replace All нажата в окне Find, даже если текстовое представление не является первым респондентом.
Перечисление 7-1 иллюстрирует ситуацию в который NSText
метод scrollRangeToVisible:
расположение сил для появления и повышения исключение.
Перечисление 7-1 , Вызывающее расположение
[[myTextView textStorage] beginEditing]; |
[[myTextView textStorage] replaceCharactersInRange:NSMakeRange(0,0) |
withString:@"Hello to you!"]; |
[myTextView scrollRangeToVisible:NSMakeRange(0,13)]; //BOOM |
[[myTextView textStorage] endEditing]; |
Прокрутка диапазона символов в видимость требует, чтобы расположение было завершено через тот диапазон, таким образом, текстовое представление может знать, где расположен диапазон. Но в Перечислении 7-1, текстовое хранение находится в пакетном режиме редактирования. Это находится в противоречивом состоянии, таким образом, у менеджера по расположению нет способа сделать расположение в это время. Перемещение scrollRangeToVisible:
вызовите после endEditing
решил бы проблему.
Существуют дополнительные меры, которые необходимо принять при реализации новых пользовательских действий в текстовом представлении, таких как метод действия меню или привязки клавиш, изменяющий текст. Например, можно изменить выбранный диапазон символов с помощью NSTextView
метод setSelectedRange:
, В зависимости от типа изменения, выполняемого командой, с помощью результатов NSTextView
методы rangeForUserTextChange
, rangeForUserCharacterAttributeChange
, или rangeForUserParagraphAttributeChange
. Например, rangeForUserParagraphAttributeChange
возвращает весь абзац, содержащий исходный выбор — который является диапазоном, затронутым, если Ваше действие изменяет атрибуты абзацев. Кроме того, необходимо вызвать textView:shouldChangeTextInRange:replacementString:
перед внесением изменения и didChangeText
впоследствии. Эти действия гарантируют, что правильный текст изменяется, и система отправляет корректные уведомления и сообщения делегата текстовому делегату представления. Посмотрите Разделение на подклассы NSTextView для получения дополнительной информации.
Принуждение конца редактирования
Могут быть ситуации, в которых необходимо вынудить текстовую систему закончить редактирование программно, таким образом, можно принять некоторые меры, зависящие от отправляемых уведомлений. В таком случае Вы не должны изменять механизм редактирования, но просто стимулировать его нормальное поведение.
Вызвать конец редактирования в текстовом представлении, впоследствии отправляющем a textDidEndEditing:
обменивайтесь сообщениями его делегату, можно наблюдать окно NSWindowDidResignKeyNotification
уведомление. Затем в методе наблюдателя отправить makeFirstResponder:
к окну для окончания любого происходящего редактирования, в то время как окно было активно. Иначе, в настоящее время редактирующееся управление остается первым респондентом окна и не заканчивает редактирование.
Перечисление 7-2 представляет реализацию textDidEndEditing:
метод делегата, заканчивающий редактирование в NSTableView
подкласс. По умолчанию, когда пользователь редактирует ячейку в табличном представлении и нажимает Tab или Return, полевой редактор редактирование концов в текущей ячейке и начинает редактировать следующую ячейку. В этом случае, если пользователь нажимает Return, Вы хотите закончить редактирование в целом. Этот метод различает, которые вводят, пользователь нажал; для Вкладки это делает нормальное поведение, и для Возврата это вызывает конец редактирования полностью путем создания окна первым респондентом.
Перечисление 7-2 , Вызывающее конец редактирования
- (void)textDidEndEditing:(NSNotification *)notification { |
if([[[notification userInfo] valueForKey:@"NSTextMovement"] intValue] == |
NSReturnTextMovement) { |
NSMutableDictionary *newUserInfo; |
newUserInfo = [[NSMutableDictionary alloc] |
initWithDictionary:[notification userInfo]]; |
[newUserInfo setObject:[NSNumber numberWithInt:NSIllegalTextMovement] |
forKey:@"NSTextMovement"]; |
notification = [NSNotification notificationWithName:[notification name] |
object:[notification object] |
userInfo:newUserInfo]; |
[super textDidEndEditing:notification]; |
[[self window] makeFirstResponder:self]; |
} else { |
[super textDidEndEditing:notification]; |
} |
} |
Установка фокуса и выбора программно
Обычно пользователь щелкает по объекту представления в окне для установки фокуса или первого состояния респондента, так, чтобы последующие события клавиатуры перешли к тому объекту первоначально. Аналогично, пользователь обычно создает выбор путем перетаскивания мыши в представлении. Однако можно установить и фокус и выбор программно.
Например, если у Вас есть окно, содержащее текстовое представление, и Вы хотите, чтобы то текстовое представление стало первым респондентом с точкой вставки, расположенной в начале любого текста в настоящее время в текстовом представлении, Вам нужна ссылка на окно и текстовое представление. Если те ссылки theWindow
и theTextView
, соответственно, можно использовать следующий код для установки фокуса и точки вставки, которая является просто диапазоном выбора нулевой длины:
[theWindow makeFirstResponder: theTextView]; |
[theTextView setSelectedRange: NSMakeRange(0,0)]; |
Когда объект, соответствующий NSTextInputClient
протокол становится первым респондентом в ключевом окне, NSTextInputContext
объект становится активным и связанным к активным источникам ввода текста, таким как палитра символов, клавиатуры и методы ввода.
Был ли выбор установлен программно или пользователем, можно добраться, диапазон символов в настоящее время выбирал использование selectedRange
метод. NSTextView
указывает его выбор путем применения специального набора атрибутов к нему. selectedTextAttributes
метод возвращает эти атрибуты, и setSelectedTextAttributes:
устанавливает их.
При изменении выбора в ответ на ввод данных пользователем, NSTextView
объект вызывает свое собственное setSelectedRange:affinity:stillSelecting:
метод. Первый параметр является диапазоном для выбора. Второе, вызванный сродство выбора, определяет, какой глиф точка вставки выводит на экран рядом, когда эти два глифа, определяющие выбранный диапазон, не смежны. Это обычно используется, где выбранные строки переносятся для размещения точки вставки в конце одной строки или начало следующей строки. Можно получить сродство выбора в настоящее время в действительности использование selectionAffinity
метод. Последний параметр указывает, является ли выбор все еще в процессе изменения; делегат и любые наблюдатели не уведомляются относительно изменения в выборе, пока метод не вызывается с NO
для этого параметра.
Другим фактором, влияющим на поведение выбора, является гранулярность выбора: выбираются ли символы, слова или целые абзацы. Это обычно определяется числом начальных щелчков мышью; например, двойной щелчок инициирует выбор уровня слова. NSTextView
решает, сколько изменить выбор во время входного отслеживания с помощью selectionRangeForProposedRange:granularity:
метод.
Дополнительным аспектом выбора, связанного с входным управлением, является диапазон отмеченного текста. Поскольку входной контекст интерпретирует ввод с клавиатуры, он может отметить неполный ввод специальным способом. Текстовое представление выводит на экран этот отмеченный текст по-другому от выбора, с помощью временных атрибутов, влияющих только на дисплей, не расположение или хранение. Например, NSTextView
использование отметило текст для отображения ключа комбинации, такого как Опция-E, помещающая символ акута выше символа, вводимого затем. Когда пользователь вводит Опцию-E, текстовое представление выводит на экран акут в желтом поле выделения, указывая, что это - отмеченный текст, а не заключительный ввод. Когда пользователь вводит следующий символ, текстовое представление выводит на экран его как единственный символ с диакритикой, и отмеченное текстовое выделение исчезает. markedRange
метод возвращает диапазон любого отмеченного текста, и markedTextAttributes
возвращается атрибуты раньше выделяли отмеченный текст. Можно изменить эти атрибуты использование setMarkedTextAttributes:
.
Разделение на подклассы NSTextView
Используя NSTextView
непосредственно самый простой способ взаимодействовать с текстовой системой, и ее механизм делегата обеспечивает чрезвычайно гибкий способ изменить ее поведение. В случаях, где делегация не обеспечивает требуемое поведение, можно разделить на подклассы NSTextView
.
Текстовая система требует NSTextView
подклассы для соблюдения определенных правил поведения, и NSTextView
обеспечивает много методов, чтобы помочь подклассам сделать так. Некоторые из этих методов предназначаются, чтобы быть переопределенными для добавления информации и поведения в основную инфраструктуру. Когда подкласс определяет свое собственное поведение, некоторые предназначаются, чтобы быть вызванными как часть той инфраструктуры.
Обновление состояния
NSTextView
автоматически обновляет окно Fonts и линейку, когда изменяется ее выбор. Если Вы добавляете какой-либо новый шрифт или атрибуты абзацев к Вашему подклассу NSTextView
, необходимо будет переопределить методы, выполняющие это обновление для учета добавленной информации. updateFontPanel
метод заставляет окно Fonts вывести на экран шрифт первого символа в выборе. Вы могли переопределить этот метод для обновления дисплея вспомогательного представление в окне Fonts. Точно так же updateRuler
заставляет линейку отображать атрибуты абзацев для первого абзаца в выборе. Можно также переопределить этот метод для настройки дисплея элементов на линейке. Обязательно вызовите super
реализация в Вашем переопределении для выполнения основного обновления также.
Пользовательские типы импорта
NSTextView
операции области монтажа поддержек и перетаскивание файлов и цветов в его текст. При настройке возможности подкласса обработать операции области монтажа для новых типов данных необходимо переопределить readablePasteboardTypes
и writablePasteboardTypes
методы для отражения тех типов. Точно так же для поддержки новых типов данных для перетаскивания операций необходимо переопределить acceptableDragTypes
метод. Ваша реализация этих методов должна вызвать реализацию суперкласса, добавить, что новые типы данных к массиву возвратились из super
, и возвратите измененный массив.
Чтобы считать и записать пользовательские типы области монтажа, необходимо переопределить readSelectionFromPasteboard:type:
и writeSelectionToPasteboard:type:
методы. В Вашей реализации этих методов необходимо считать новые типы данных поддержки подкласса и позволить суперклассу обработать любые другие типы.
Для перетаскивания операций, если возможность Вашего подкласса принять Ваши пользовательские типы перетаскивания варьируется в течение долгого времени, можно переопределить updateDragTypeRegistration
зарегистрировать или не зарегистрировать пользовательские типы согласно текстовому текущему статусу представления. Если получатель доступен для редактирования и представление обогащенного текста, по умолчанию этот метод позволяет перетащить всех приемлемых типов.
Изменение поведения выбора
Ваш подкласс NSTextView
может настроить способ, которым выборы сделаны для различных гранулярностей (таких как символ, слово и абзац) описанным вставляющим Фокусом и Выбором Программно. В то время как отслеживание пользователя изменяется на выбор, NSTextView
объект неоднократно вызывает selectionRangeForProposedRange:granularity:
определить что диапазон фактически выбрать. Когда закончено отслеживая изменения, это отправляет делегата a textView:willChangeSelectionFromCharacterRange:toCharacterRange:
сообщение. Путем переопределения NSTextView
метод или реализация метода делегата, можно изменить способ, которым выбор расширен или сокращен. Например, в редакторе кода можно предоставить делегату, расширяющему двойной щелчок по фигурной скобке или символу круглой скобки к его соответствию разделителя.
Эти механизмы не предназначены для изменения определений слова языка (такой как, что выбрано двойным щелчком). Та подробность выбора обрабатывается в более низком (и в настоящее время частная) уровень текстовой системы.
Подготовка изменить текст
Если Вы создаете подкласс NSTextView
для добавления новых возможностей, которые изменят текст в ответ на пользовательские действия Вы, возможно, должны изменить диапазон, выбранный пользователем прежде фактически применить изменение. Например, если пользователь вносит изменение в линейку, изменение должно примениться к целым абзацам, таким образом, выбор, вероятно, придется расширить на границы абзаца. Три метода вычисляют диапазон, к которому должны применяться определенные виды изменения. rangeForUserTextChange
метод возвращает диапазон, к которому должно применяться любое изменение в самих символах — вставках и удалениях —. rangeForUserCharacterAttributeChange
метод возвращает диапазон, к которому должно применяться изменение символьного атрибута, такое как новый шрифт или цвет. Наконец, rangeForUserParagraphAttributeChange
возвращает диапазон для изменения уровня абзаца, такого как новая или перемещенная позиция табуляции или отступ. Эти методы весь возврат диапазон, расположение которого NSNotFound
если изменение не возможно; необходимо проверить возвращенный диапазон и отказаться от изменения в этом случае.
Текстовые уведомления изменения и сообщения делегата
В фактическом внесении изменений в текст необходимо гарантировать, что изменения должным образом выполнены и зарегистрированы различными частями текстовой системы. Вы делаете это путем заключения в скобки каждого пакета потенциальных изменений с shouldChangeTextInRange:replacementString:
и didChangeText
сообщения. Эти методы гарантируют, что соответствующий делегат обменивается сообщениями, отправляются, и уведомления отправляются. Первый метод спрашивает делегата к разрешению начать редактировать с a textShouldBeginEditing:
сообщение. Если возвращается делегат NO
, shouldChangeTextInRange:replacementString:
поочередно возвраты NO
, когда Ваш подкласс должен запретить изменение. Если возвращается делегат YES
, текстовое представление отправляет NSTextDidBeginEditingNotification
, и shouldChangeTextInRange:replacementString:
поочередно возвраты YES
. В этом случае можно внести изменения в текст и проконтролировать путем вызова didChangeText
. Этот метод завершает изменения путем регистрации NSTextDidChangeNotification
, который приводит к делегату, получающему a textDidChange:
сообщение.
textShouldBeginEditing:
и textDidBeginEditing:
сообщения отправляются только один раз во время сеанса редактирования. Более точно они отправляются на первый ввод данных пользователем начиная с NSTextView
стал первым респондентом. После того, эти сообщения — и NSTextDidBeginEditingNotification
— пропускаются в последовательности. textView:shouldChangeTextInRange:replacementString:
метод, однако, должен быть вызван для каждого отдельного изменения.
Умная вставка и удаляет
NSTextView
определяет несколько методов для помощи в «умной» вставке и удалении текста, так, чтобы интервал и пунктуация был сохранен после изменения. Когда пользователь выбрал целые слова или другие значительные модули текста, умная вставка и удаление обычно применяются. Умное удаление слова перед запятой, например, также удаляет пространство, которое иначе оставили бы перед запятой (не поместив его на области монтажа в операции Cut). Умная вставка слова между другим словом и запятой добавляет пространство между этими двумя словами для защиты той границы. NSTextView
автоматически использует умную вставку и удаление по умолчанию; можно повернуть это поведение от использования setSmartInsertDeleteEnabled:
. Выполнение так заставляет только выделенный текст быть удаленным, и вставленный текст, который будет добавлен без добавления пробела.
Если Ваш подкласс NSTextView
определяет любые методы, вставляющие или удаляющие текст, можно сделать их умными путем использования в своих интересах два NSTextView
методы. smartDeleteRangeForProposedRange:
метод разворачивает предложенный диапазон удаления для включения любого пробела, который должен также быть удален. Если необходимо сохранить удаленный текст, однако, обычно лучше сохранить только текст от исходного диапазона. Для умной вставки, smartInsertForString:replacingRange:beforeString:afterString:
возвраты ссылкой две строки, которые можно вставить прежде и после данной строки для сохранения интервала и пунктуации. См. описания метода для получения дополнительной информации.
Создание представления пользовательского текста
Стратегия, еще более сложная, чем разделение на подклассы NSTextView
должен создать Ваш собственный текстовый объект представления. Если Вам нужна более сложная текстовая обработка, чем NSTextView
обеспечивает, например одним словом, приложение обработки, возможно создать текстовое представление путем разделения на подклассы NSView
, реализация NSTextInputClient
протокол, и взаимодействующий непосредственно с входной системой управления.
Реализация поддержки ввода текста
Пользовательские представления Какао могут обеспечить переменные уровни поддержки системы ввода текста. Существует по существу три уровня поддержки для выбора из:
Переопределите
keyDown:
метод.Переопределение
keyDown:
и используйтеhandleEvent:
поддерживать привязки клавиш.Также реализуйте полное
NSTextInputClient
протокол.
На первом уровне поддержки, keyDown:
метод распознает ограниченный набор событий и игнорирует других. Этот уровень поддержки типичен для игр. (При переопределении keyDown:
, необходимо также переопределить acceptsFirstResponder
заставить Ваше пользовательское представление реагировать на ключевые события, как описано в “Основах Обработки событий” в Руководстве по Обработке событий Какао.)
На втором уровне поддержки можно переопределить keyDown:
и используйте handleEvent:
метод для получения поддержки привязки клавиш, не реализовывая NSTextInputClient
протокол. Поскольку NSView
метод inputContext
не инстанцирует NSTextInputContext
автоматически, если представление не соответствует NSTextInputClient
, пользовательское представление должно инстанцировать его вручную. Вы тогда реализуете стандартные методы привязки клавиш, которые Ваше представление хочет поддерживать, такой как moveForward:
или deleteForward:
. (Полный список методов привязки клавиш может быть найден в NSResponder.h
.)
Если Вы пишете свое собственное текстовое представление с нуля, необходимо использовать третий уровень поддержки и реализовать NSTextInputClient
протокол в дополнение к переопределению keyDown:
и использование handleEvent:
. NSTextView
и его подклассы являются единственными классами, предоставленными в Какао та реализация NSTextInputClient
, и если для Вашего приложения нужно более сложное поведение, чем NSTextView
может обеспечить, как текстовой процессор мог бы, Вы, возможно, должны реализовать текстовое представление с нуля. Чтобы сделать это, необходимо разделить на подклассы NSView
и реализация NSTextInputClient
протокол. (Класс, реализовывая этот протокол — путем наследования от NSTextView
или путем реализации протокола непосредственно — вызывается текстовым представлением.)
Если Вы реализуете NSTextInputClient
протокол, Ваше представление должно управлять отмеченным текстом и связаться с контекстом ввода текста для поддержки системы ввода текста. Эти задачи описаны в следующих двух разделах.
Управление отмеченным текстом
Одна из основных вещей, которые текстовое представление должно сделать для сотрудничества с входным контекстом, состоит в том, чтобы поддержать (возможно пустой) диапазон отмеченного текста в его текстовом хранении. Текстовое представление должно выделить текст в этом диапазоне отличительным способом, и это должно позволить выбор в отмеченном тексте. Текстовое представление должно также поддержать точку вставки, которая является обычно в конце отмеченного текста, но пользователь может поместить его в отмеченном тексте. Текстовое представление также поддерживает (возможно пустой) диапазон выбора в его текстовом хранении, и если существует какой-либо отмеченный текст, выбор должен быть полностью в отмеченном тексте.
Когда пользователь вводит символ с многократными нажатиями клавиш, такими как «В», в, типичный пример отмеченного текста появляется NSTextView
объект. Для ввода этого символа пользователь должен ввести Опцию-E, сопровождаемую ключом E. После нажатия Option-E метка диакритического знака появляется в выделенном поле, указывая, что текст отмечен (не окончательный). После финала нажимается E, «В» символ появляется, и выделение исчезает.
Связь с контекстом ввода текста
Текстовое представление и контекст ввода текста должны сотрудничать так, чтобы входной контекст мог реализовать свой пользовательский интерфейс. NSTextInputContext
класс представляет интерфейс системе ввода текста, т.е. состоянию или контексту, уникальному для его объекта клиента, такого как состояние привязки клавиш, сеанс связи метода ввода, и т.д. Большая часть NSTextInputClient
методы протокола вызывает входной контекст для управления текстом в текстовом представлении во входных целях пользовательского интерфейса контекста.
Каждый NSTextInputClient
- совместимый объект (обычно NSView
подкласс), имеет его собственное NSTextInputContext
экземпляр. Реализация по умолчанию NSView
метод inputContext
управляет NSTextInputContext
инстанцируйте автоматически, если подкласс представления соответствует NSTextInputClient
протокол.
Когда событие от нажатия мыши или событие клавиатуры происходят путем отправки, текстовое представление должно сообщить текущему менеджеру по вводу handleEvent:
обменивайтесь сообщениями к текущему входному контексту. Когда его отмеченный текстовый диапазон больше не необходим, текстовое представление отправляет a discardMarkedText
обменивайтесь сообщениями к текущему входному контексту.
Кроме того, текстовое представление должно сказать входной контекст, когда информация о положении для диапазона символов изменяется, такой как тогда, когда текстовое представление прокручивает путем отправки invalidateCharacterCoordinates
обменивайтесь сообщениями к входному контексту. Входной контекст может тогда обновить информацию, ранее запрошенную через методы как firstRectForCharacterRange:actualRange:
когда, например, это хочет показать всплывающее меню выбора для отмеченного текста (как с японским методом ввода). Существует дополнительный метод, drawsVerticallyForCharacterAtIndex:
, это может сообщить системе ввода текста, представляет ли приспосабливающий протоколу клиент символ в данном индексе вертикально.
Входной контекст обычно использует все методы в NSTextInputClient
протокол. Когда раскладка клавиатуры изменяется, можно также зарегистрироваться для получения уведомления из входного контекста.
Для получения дополнительной информации обратитесь к Ссылке класса NSText, Ссылке класса NSTextView, Ссылке класса NSView, Ссылке класса NSTextInputContext и Ссылке на протокол NSTextInputClient.
Работа с полевым редактором
Этот раздел объясняет, как текстовая система Какао использует полевого редактора и как можно изменить то поведение. В большинстве случаев Вы не должны быть обеспокоены полевым редактором, потому что Какао обрабатывает свою работу автоматически, негласно. Однако хорошо знать о его существовании, и возможно, что при некоторых обстоятельствах Вы могли хотеть изменить его поведение.
Как работает полевой редактор
Текстовая система автоматически инстанцирует полевого редактора от NSTextView
класс, когда пользователь начинает редактировать текст NSControl
возразите, такие как текстовое поле. В то время как это редактирует, система вводит полевого редактора в цепочку респондента как первый респондент, таким образом, это получает события нажатия клавиши вместо текстового поля или другого объекта управления. Когда сдвиги фокуса к другому текстовому полю, полевой редактор присоединяется к тому полю вместо этого. Полевой редактор определяет поле текущего текста как его делегата, позволяющего текстовому полю управлять изменениями в своем содержании. Если Вы не знакомы с работами полевого редактора, потому что, этот механизм может сбить с толку NSWindow
метод firstResponder
возвращает полевого редактора, который не видим, а не экранный объект, в настоящее время имеющий клавиатурный фокус.
Среди его других режимов работы полевой редактор поддерживает выбор для текстовых полей, которые он редактирует. Поэтому текстовое поле, это не редактируется, не имеет выбора (если Вы не кэшируете его).
Полевой редактор определяется его обработкой определенных символов во время ввода текста, отличающегося от обычного текстового представления. Обычное текстовое представление вставляет новую строку, когда пользователь нажимает Return или Enter, это вставляет символ табуляции, когда пользователь нажимает Tab, и это игнорирует Shift-Tab. Напротив, полевой редактор интерпретирует эти символы как сигналы, чтобы закончить редактирование и оставить первое состояние респондента, смещая фокус к следующему объекту в цикле ключевого представления (или в случае Shift-Tab, предыдущего ключевого представления).
Конец редактирования триггерной синхронизации содержания полевого редактора и NSTextFieldCell
возразите что редактирование средств управления в текстовом поле. В той точке Какао отсоединяет полевого редактора от текстового поля и показывает текстовое поле наверху иерархии представления.
Используя делегацию и уведомление с полевым редактором
Один из способов, которыми можно управлять поведением редактирования текстовых полей, путем взаимодействия с полевым редактором через делегацию и уведомление. Поскольку полевой редактор автоматически определяет любое текстовое поле, которое это редактирует как его делегат, можно часто инкапсулировать специальное поведение редактирования для текстового поля с самим текстовым полем.
Изменение поведения по умолчанию
Это прямо для изменения поведения по умолчанию полевого редактора путем реализации методов делегата. Например, делегат может изменить поведение, происходящее, когда пользователь нажимает Return при редактировании текстового представления. По умолчанию то редактирование концов действия и выбирает следующее управление в ключевом цикле представления. Если, например, Вы хотите нажатие Return для окончания редактирования, но не выбрать следующее управление, можно реализовать textDidEndEditing:
метод делегата в текстовом поле. Полевой редактор автоматически вызывает этот метод, если делегат реализует его, и передачи NSTextDidEndEditingNotification
. Реализация может исследовать это уведомление для обнаружения события, закончившего редактирование, и ответьте соответственно.
Получение новых строк в объект NSTextField
Пользователи могут легко поместить символы новой строки в текстовое поле путем нажатия Option-Return, или Option - Входят. Однако могут быть ситуации, в которые Вы хотите позволить пользователям вводить новые строки, не принимая специальных мер, и можно сделать так путем реализации метода делегата.
Самый простой подход должен вызвать setFieldEditor:NO
на полевом редакторе окна. Но, конечно, этот подход изменяет поведение полевого редактора для всех средств управления. Другой подход должен использовать NSControl
сообщение делегата control:textShouldBeginEditing:
, когда пользователь вводит символ в текстовое поле, который отправляется текстовому делегату представления. Поскольку это передает ссылки и на текстовое представление и на полевого редактора, Вы могли протестировать, чтобы видеть, ли текстовое представление один, в который Вы хотите ввести новые строки, тогда затем отправить setFieldEditor:NO
полевому редактору. Однако этот метод не вызывают, пока пользователь не ввел один символ в текстовое поле, и если тот символ является новой строкой, это отклоняется.
Лучший метод должен реализовать другого NSControl
метод делегата, control:textView:doCommandBySelector:
, который позволяет делегату текстового поля проверить, пытается ли пользователь вставить символ новой строки и, если так, вызвать к полевому редактору для вставки его. Реализация могла появиться как показано в Перечислении 7-3.
Перечисление 7-3 , Вынуждающее полевого редактора ввести символ новой строки
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor |
doCommandBySelector:(SEL)commandSelector { |
BOOL retval = NO; |
if (commandSelector == @selector(insertNewline:)) { |
retval = YES; |
[fieldEditor insertNewlineIgnoringFieldEditor:nil]; |
} |
return retval; |
} |
Этот метод возвраты YES
указать, что это обрабатывает эту определенную команду и NO
для других команд, которые это не обрабатывает. Этот подход имеет преимущество, что это не изменяет установку полевого редактора, но обрабатывает просто особый случай интереса. Поскольку сообщение делегата включает ссылку на отредактированное управление, Вы могли добавить проверку для ограничения поведения определенным классом, такой как NSTextField
, или отдельный подкласс.
Используя пользовательского полевого редактора
Для настройки поведения способами, идущими вне того, что может сделать делегат необходимо определить подкласс NSTextView
это включает Ваше специализированное поведение, и замените им полевого редактора окна по умолчанию.
Почему использование пользовательский полевой редактор?
Если просто необходимо проверить, интерпретировать, отформатировать, или даже отредактировать содержание текстовых полей как пользовательские типы, не необходимо использовать пользовательского полевого редактора. Можно присоединить NSFormatter
, такой как NSNumberFormatter
, NSDateFormatter
, или пользовательское средство форматирования, с этой целью. Посмотрите Руководство по Форматированию данных для получения дополнительной информации об использовании средств форматирования. Делегация и уведомление также предоставляют много возможностей для Вас для вмешательства, как описано в Использовании Делегации и Уведомления с Полевым Редактором.
Безопасное текстовое поле является примером действительно специализированной обработки данных, идущих вне того, что может быть обоснованно обработано средствами форматирования или делегатами. Безопасное текстовое поле должно принять текстовые данные, вводимые пользователем, и проверить записи, легко сделанные с полем обычного текста и средством форматирования. Но это должно вывести на экран некоторые поддельные символы для держания реальных данных в секрете, в то время как это сохраняет реальные данные для процесса аутентификации или другой цели. Кроме того, безопасное текстовое поле должно бережно хранить свои данные от несанкционированного доступа путем отключения опций, таких как копия и сократить, и возможно шифрования данных. Для реализации этих специализированных требований является самым простым развернуть пользовательского полевого редактора. Фактически, Какао реализует пользовательского полевого редактора в NSSecureTextField
класс.
Любая ситуация, требующая необычной обработки данных, ввела в текстовое поле или другое индивидуализированное поведение, не доступное через стандартные механизмы Какао, хороший кандидат на пользовательского полевого редактора.
Как заменить пользовательским полевым редактором
Можно заменить пользовательским полевым редактором вместо версии окна по умолчанию путем реализации NSWindow
метод делегата windowWillReturnFieldEditor:toObject:
. Вы реализуете этот метод в делегате окна, который мог быть, например, объектом контроллера окна. Окно отправляет это сообщение своему делегату с собой и объектом, запрашивающим полевого редактора как параметры. Так, можно протестировать объект и сделать замену пользовательского полевого редактора зависящей от результата. Окно продолжает использовать своего полевого редактора по умолчанию для других средств управления.
Например, реализация, показанная в Перечислении 7-4, тестирует, инстанцируют ли объект запроса от полевого названного класса пользовательского текста CustomTextField
, и, если это, возвращает пользовательского полевого редактора.
Перечисление 7-4 , Заменяющее пользовательским полевым редактором
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)anObject |
{ |
if ([anObject isKindOfClass:[CustomTextField class]]) |
{ |
if (!myCustomFieldEditor) { |
myCustomFieldEditor = [[CustomFieldEditor alloc] init]; |
[myCustomFieldEditor setFieldEditor:YES]; |
} |
return myCustomFieldEditor; |
} |
return nil; |
} |
Если объект запроса не является полем пользовательского текста или подклассом, возвратами метода делегата nil
и окно использует своего полевого редактора по умолчанию. Это расположение имеет преимущество, что это не инстанцирует пользовательского полевого редактора, если это не необходимо.
В OS X v10.6 и позже, другой способ предоставить пользовательскому полевому редактору состоит в том, чтобы переопределить NSCell
метод fieldEditorForView:
. Этот метод, а не метод делегата окна, более подходит для пользовательских подклассов ячейки.
Можно найти больше информации о разделении на подклассы NSTextView
в разделении на подклассы NSTextView.
Поле связанные с редактором методы
Этот раздел перечисляет методы AppKit, наиболее непосредственно связанные с полевым редактором. Можно просмотреть эти таблицы для понимания, где Какао предоставляет возможности для Вас для взаимодействия с полевым редактором. Обратитесь к Ссылке Платформы AppKit для подробных данных. NSWindow
методы, связанные с полевым редактором, перечислены в Таблице 7-1.
NSTextFieldCell
метод, связанный с полевым редактором, перечислен в Таблице 7-2.
Метод | Описание |
---|---|
Вы никогда не вызываете этот метод непосредственно; путем переопределения его, однако, можно настроить полевого редактора. |
NSCell
методы, связанные с полевым редактором, перечислены в Таблице 7-3.
NSControl
методы, связанные с полевым редактором, перечислены в Таблице 7-4. NSControl
методы делегата, перечисленные в Таблице 7-4, являются специфичными для управления версиями методов делегата и уведомлений, определенных NSText
. Полевой редактор, полученный из NSText
, инициирует отправку сообщений делегата и уведомлений посредством ее действий редактирования.
NSResponder
методы, связанные с полевым редактором, перечислены в Таблице 7-5.
NSText
и NSTextDelegate
методы, связанные с полевым редактором, перечислены в Таблице 7-6.
Метод | Описание |
---|---|
Возвраты | |
Средства управления, интерпретирует ли получатель Вкладку, Shift-Tab и Возврат (Входят) как сигналы, чтобы закончить редактирование и возможно изменить первого респондента. | |
Сообщает делегату, что пользователь начал изменять текст, передав | |
Сообщает делегату, что текстовый объект изменил свои символы или атрибуты форматирования, передав | |
Сообщает делегату, что текстовый объект закончил редактировать (что он оставил первое состояние респондента), передавая | |
Вызванный от реализации текстового объекта | |
Вызванный от реализации текстового объекта |