привязка NSTextField к NSNumber - PullRequest
       13

привязка NSTextField к NSNumber

5 голосов
/ 09 февраля 2009

Я пытаюсь использовать NSTextField для целочисленного пользовательского ввода. Текстовое поле привязано к свойству NSNumber, и в методе установки я очищаю входное значение (убедитесь, что это int) и устанавливаю свойство при необходимости. Я отправляю willChangeValueForKey: и didChangeValueForKey:, но пользовательский интерфейс не обновляется до новых значений, пока это текстовое поле все еще активно.

Так, например, я могу ввести «12abc» в текстовое поле, которое метод установки очищает до «12», но в текстовом поле все еще отображается «12abc».

У меня проверено «Постоянно обновляемое значение» в конструкторе интерфейсов.

(Я также заметил, что метод установки получает NSString, а не NSNumber. Это нормально?)

Как правильно подключить NSTextField к NSNumber? Как выглядит метод установки для свойства? Как предотвратить отображение нечисловых значений в текстовом поле?

Ответы [ 4 ]

10 голосов
/ 09 февраля 2009

Я отправляю willChangeValueForKey: и didChangeValueForKey:, но пользовательский интерфейс не обновляется до новых значений, пока текстовое поле все еще активно.

Существует очень мало причин для отправки этих сообщений. Обычно вы можете выполнять ту же работу лучше и чище, внедряя и используя методы доступа (или, что еще лучше, свойства). KVO отправит вам уведомления, когда вы это сделаете.

В вашем случае вы хотите либо отклонить, либо отфильтровать поддельные входы (например, «12abc»). Правильный инструмент для этой задачи - Проверка значения ключа.

Чтобы включить это, установите флажок «Проверять немедленно» на привязке в IB и внедрить метод проверки.

Фильтрация:

- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError {
    NSString *salvagedNumericPart;
    //Determine whether you can salvage a numeric part from the string; in your example, that would be “12”, chopping off the “abc”.
    *newValue = salvagedNumericPart; //@"12"
    return (salvagedNumericPart != nil);
}

Отвергая:

- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError {
    BOOL isEntirelyNumeric;
    //Determine whether the whole string (perhaps after stripping whitespace) is a number. If not, reject it outright.
    if (isEntirelyNumeric) {
        //The input was @"12", or it was @" 12 " or something and you stripped the whitespace from it, so *newValue is @"12".
        return YES;
    } else {
        if (outError) {
            *outError = [NSError errorWithDomain:NSCocoaErrorDomain code: NSKeyValueValidationError userInfo:nil];
        }
        //Note: No need to set *newValue here.
        return NO;
    }
}

(Я также заметил, что метод установки получает NSString, а не NSNumber. Это нормально?)

Да, если только вы не используете преобразователь значения, который преобразует строки в числа, подключите средство форматирования чисел к выходу formatter или замените NSNumber для NSString в вашем методе проверки.

2 голосов
/ 07 мая 2009

Есть важный комментарий к отличному ответу Питера Хоси, который я хотел бы поднять на высший уровень (потому что я пропустил его при первом проходе).

Если вы хотите проверять / изменять NSTextField каждый раз, когда вводится символ, а не только когда пользователь отправляет поле, то вы не можете получить то, что хотите, только с помощью привязок. Вам необходимо назначить делегата в текстовое поле, а затем внедрить - (void)controlTextDidChange:(NSNotification *)aNotification в делегат. Это будет вызываться каждый раз, когда текст меняется. Если хотите, вы можете вызвать валидатор значения в controlTextDidChange.

Например:

- (void)controlTextDidChange:(NSNotification *)aNotification
{
    NSError *outError;
    NSControl *textField = [aNotification object];
    NSString *myText = [textField stringValue];

    // myObject is the model object that owns the text in question
    // the validator can modify myText by reference
    [myObject validateValue:&myText error:&outError]];

    // update the NSNextField with the validated text
    [postingObject setStringValue:myText];
}
1 голос
/ 09 февраля 2009

Как уже упоминал Бен, один из способов сделать это - присоединить NSNumberFormatter к вашему текстовому полю, что довольно просто настроить в конструкторе интерфейсов и, скорее всего, будет просто работать ™.

Если вам не нравятся модальные диалоги, которые NSNumberFormatter бросает на ваших пользователей, когда они вводят нечисловые значения, вы можете создать подкласс NSNumberFormatter для реализации другого, более «прощающего» поведения форматирования. Я думаю, что переопределение - numberFromString: вырезать нечисловые символы перед вызовом реализации super должно помочь.

Другой подход заключается в создании и регистрации вашего собственного подкласса NSValueTransformer для разбора строк в NSNumbers и обратно, но я бы сначала попробовал использовать NSNumberFormatter, поскольку это довольно ясно класс, который был разработан для этой конкретной цели.

Подробнее о преобразователях стоимости

0 голосов
/ 09 февраля 2009

Я думаю, вам нужно настроить числовой форматер на ваш NSTextField.

Читайте о форматерах на сайте Apple: Применение форматеров .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...