Почему valueForKey: на UITextField генерируется исключение для свойств UITextInputTraits?

Запуск:

@try
{
    NSLog(@"1. autocapitalizationType = %d", [self.textField autocapitalizationType]);
    NSLog(@"2. autocapitalizationType = %@", [self.textField valueForKey:@"autocapitalizationType"]);
}
@catch (NSException *exception)
{
    NSLog(@"3. %@", exception);
}

Выводит следующее:

1. autocapitalizationType = 0
3. [<UITextField 0x6c15df0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key autocapitalizationType.

Я ожидал:

1. autocapitalizationType = 0
2. autocapitalizationType = 0

Это исключение происходит только со свойствами, которые являются частью протокола UITextInputTraits. Регулярные свойства a UITextField такие, что clearButtonMode можно получить через valueForKey:.

Итак, почему вы не можете получить доступ к свойствам UITextInputTraits с ключом-значением?

Ответ 1

Если вы вникаете в структуру UIKit и открываете UITextField.h, вы найдете:

@interface UITextField : UIControl <UITextInput, NSCoding> {
  @private

    UITextInputTraits  *_traits;
    UITextInputTraits  *_nonAtomTraits;

Вы также обнаружите, что clearButtonMode объявлен как @property в заголовочном файле UITextField, но это autocapitalizationType (и остальная часть протокола UITextInputTraits) не являются.

Мы с вами не видим UITextField.m, поэтому мы можем заключить, что Apple внедрила протокол UITextField UITextInputTraits таким образом, чтобы не соответствовать требованиям KVC. Предположительно, код клея где-то преобразует [myTextField autocapitalizationType] в соответствующее значение, но все, что происходит за кадром, останавливается до valueForKey:.

Ответ 2

Вот мой обход: я swizzled valueForKey: для каждого класса, реализующего метод textInputTraits. Если ключ является ключом UITextInputTraits, тогда вызов valueForKey: на объект textInputTraits вместо самого объекта.

Вот подробности реализации: 1, 2 и 3.