Skip to content
This repository has been archived by the owner on Dec 19, 2017. It is now read-only.

Commit

Permalink
Workaround non KVC compliant UITextInputTraits properties
Browse files Browse the repository at this point in the history
  • Loading branch information
0xced committed Jul 8, 2011
1 parent be81d0e commit 8303b1c
Showing 1 changed file with 58 additions and 2 deletions.
60 changes: 58 additions & 2 deletions DCIntrospect/DCIntrospect.m
Expand Up @@ -46,6 +46,7 @@ + (void)load
CFStringRef accessibilityDomain = CPCopySharedResourcesPreferencesDomainForDomain(CFSTR("com.apple.Accessibility"));
if (accessibilityDomain)
{
// This must be done *before* UIApplicationMain, hence +load
CFPreferencesSetValue(CFSTR("ApplicationAccessibilityEnabled"), kCFBooleanTrue, accessibilityDomain, kCFPreferencesAnyUser, kCFPreferencesAnyHost);
CFRelease(accessibilityDomain);
}
Expand All @@ -55,6 +56,61 @@ + (void)load
[pool drain];
}

static void *originalValueForKeyIMPKey = &originalValueForKeyIMPKey;

id UITextInputTraits_valueForKey(id self, SEL _cmd, NSString *key);
id UITextInputTraits_valueForKey(id self, SEL _cmd, NSString *key)
{
static NSMutableSet *textInputTraitsProperties = nil;
if (!textInputTraitsProperties)
{
textInputTraitsProperties = [[NSMutableSet alloc] init];
unsigned int count = 0;
objc_property_t *properties = protocol_copyPropertyList(@protocol(UITextInputTraits), &count);
for (unsigned int i = 0; i < count; i++)
{
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
[textInputTraitsProperties addObject:propertyName];
}
free(properties);
}

IMP valueForKey = [objc_getAssociatedObject([self class], originalValueForKeyIMPKey) pointerValue];
if ([textInputTraitsProperties containsObject:key])
{
id textInputTraits = valueForKey(self, _cmd, @"textInputTraits");
return valueForKey(textInputTraits, _cmd, key);
}
else
{
return valueForKey(self, _cmd, key);
}
}

// See http://stackoverflow.com/questions/6617472/why-does-valueforkey-on-a-uitextfield-throws-an-exception-for-uitextinputtraits
+ (void)workaroundUITextInputTraitsPropertiesBug
{
Method valueForKey = class_getInstanceMethod([NSObject class], @selector(valueForKey:));
const char *valueForKeyTypeEncoding = method_getTypeEncoding(valueForKey);

unsigned int count = 0;
Class *classes = objc_copyClassList(&count);
for (unsigned int i = 0; i < count; i++)
{
Class class = classes[i];
if (class_conformsToProtocol(class, @protocol(UITextInputTraits)))
{
IMP originalValueForKey = class_replaceMethod(class, @selector(valueForKey:), (IMP)UITextInputTraits_valueForKey, valueForKeyTypeEncoding);
if (!originalValueForKey)
originalValueForKey = class_getMethodImplementation([class superclass], @selector(valueForKey:));

objc_setAssociatedObject(class, originalValueForKeyIMPKey, [NSValue valueWithPointer:originalValueForKey], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
free(classes);
}

+ (DCIntrospect *)sharedIntrospector
{
#ifdef DEBUG
Expand All @@ -63,6 +119,7 @@ + (DCIntrospect *)sharedIntrospector
sharedInstance = [[DCIntrospect alloc] init];
sharedInstance.keyboardBindingsOn = YES;
sharedInstance.showStatusBarOverlay = ![UIApplication sharedApplication].statusBarHidden;
[self workaroundUITextInputTraitsPropertiesBug];
}
#endif
return sharedInstance;
Expand Down Expand Up @@ -1315,8 +1372,7 @@ - (void)logPropertiesForObject:(id)object
}
@catch (NSException *exception)
{
// Non KVC compliant properties, e.g. UITextInputTraits properties of UITextField
// See http://stackoverflow.com/questions/6617472/why-does-valueforkey-on-a-uitextfield-throws-an-exception-for-uitextinputtraits
// Non KVC compliant properties, see also +workaroundUITextInputTraitsPropertiesBug
propertyDescription = @"N/A";
}
[outputString appendFormat:@" %@: %@\n", propertyName, propertyDescription];
Expand Down

0 comments on commit 8303b1c

Please sign in to comment.