#objective-c #cocoa #macos #listener #nstextfield
#objective-c #cocoa #macos #прослушиватель #nstextfield
Вопрос:
Я пытаюсь понять, как перехватить событие «текст изменен» из текстового поля в моем окне. Я привык к Java «action listeners» и не могу найти ничего подобного в Objective-C / Cocoa. Я довольно долго искал и нашел протокол «наблюдения за значением ключа», но observeValueForKeyPath:
метод (функция?) срабатывает только тогда, когда значение моего текстового поля было изменено в коде (с помощью [textfield setStringValue:...]
, например), а не путем ввода в нем.
Как я могу «прослушать» изменение значения, когда пользователь вводит текстовое поле?
Ответ №1:
Вы можете установить делегат для своего NSTextField
экземпляра и попросить делегата реализовать следующий метод:
- (void)controlTextDidChange:(NSNotification *)notification {
// there was a text change in some control
}
Вашим объектом делегирования может быть делегат приложения, контроллер окна, контроллер представления или какой-либо другой объект в вашем приложении. Делегат может быть программно установлен через
[myTextField setDelegate:delegateObject];
или, в Interface Builder, через delegate
выход, доступный в NSTextField
элементе управления.
Обратите внимание, что если к одному и тому же делегату подключено несколько элементов управления, то -controlTextDidChange:
будет отправлено для каждого элемента управления, т. е. один и тот же метод вызывается для разных элементов управления. Если вы хотите изменить поведение в зависимости от элемента управления, в котором изменился текст, вы можете использовать -[NSNotification object]
для идентификации элемента управления, отправившего уведомление.
Например, если у вас есть два текстовых поля с соответствующими выходами nameField
и addressField
, и вы установили одинаковый делегат для обоих полей, то:
- (void)controlTextDidChange:(NSNotification *)notification {
// there was a text change in some control
// [notification object] points to the control that has sent
// the notification
if ([notification object] == nameField) {
// nameField has changed
}
else if ([notification object] == addressField) {
// addressField has changed
}
}
В качестве альтернативы, у вас могло бы быть по одному делегату для каждого текстового поля. В этом случае не было бы необходимости тестировать [notification object]
.
Комментарии:
1. спасибо, это было следующее, что я искал! я подумал, что неудобно создавать новые классы для каждого объекта, которому требуется делегат
2. @Eike Обратите внимание, что ответ Киприана предназначен для iOS и использует неправильный метод для того, что вы хотите.
…shouldBeginEditing:
реализуется, когда вы хотите контролировать, должно ли текстовое поле разрешать редактирование текста.3. побочный вопрос: кто-нибудь понимает, как предсказать , будет ли данное событие доступно через IB или потребуется механизм делегирования? Это оценка Apple того, как часто будет использоваться событие, или это что-то более формальное?
Ответ №2:
Вы также можете просто подключиться к «Редактирование изменено» из IB и создать действие для его обработки
- (IBAction)txtField_Changed:(id)sender
{
// my textfield has been changed
}
Ответ №3:
Это работает для меня
func textView(textView: NSTextView, shouldChangeTextInRange affectedCharRange: NSRange, replacementString: String?) -> Bool {
print("Changed!")
return true
}
Ответ №4:
Вы можете использовать textFieldShouldBeginEditing:
метод UITextFieldDelegate
. В iOS прослушиватели называются NSNotifications
Редактировать
В objective-c многие UIObjects имеют соответствующий класс протокола, который называется «делегат», делегат отвечает за реагирование на события. Итак, чтобы иметь возможность отвечать или получать уведомления о действиях, вам необходимо реализовать делегат и его методы.
Комментарии:
1. неправильная ОС (OSX не iOS), неправильный класс управления (NSTextField не UITextField)
2. Извините, но уведомление не является прослушивателем. Вы добавляете себя в качестве наблюдателя в Центр уведомлений, чтобы получать уведомления.