Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does valueForKey: on a UITextField throws an exception for UITextInputTraits properties?

Running this:

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

Outputs this:

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

I was expecting:

1. autocapitalizationType = 0
2. autocapitalizationType = 0

This exception only happens with properties that are part of the UITextInputTraits protocol. Regular properties of a UITextField such has clearButtonMode can be accessed through valueForKey:.

So why can't you access UITextInputTraits properties with key-value coding?

like image 209
0xced Avatar asked Jul 07 '11 21:07

0xced


2 Answers

If you delve into the UIKit framework and open up UITextField.h, you'll find:

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

    UITextInputTraits  *_traits;
    UITextInputTraits  *_nonAtomTraits;

You'll also find that clearButtonMode is declared as a @property in the UITextField header file, but that autocapitalizationType (and the rest of the UITextInputTraits protocol) are not.

You and I don't get to see UITextField.m, so all we can really conclude is that Apple implemented the UITextField's UITextInputTraits protocol in a way that's not KVC compliant. Presumably glue code somewhere converts [myTextField autocapitalizationType] into the appropriate value, but whatever behind-the-scenes magic is taking place stops short of valueForKey:.

like image 87
Scott Forbes Avatar answered Oct 29 '22 15:10

Scott Forbes


Here is my workaround: I swizzled valueForKey: for every class implementing the textInputTraits method. If the key is a UITextInputTraits key, then call valueForKey: on the object's textInputTraits instead of the object itself.

Here are the implementation details: 1, 2 and 3.

like image 40
0xced Avatar answered Oct 29 '22 14:10

0xced