Permalink
Browse files

Workaround non KVC compliant UITextInputTraits properties

  • Loading branch information...
0xced committed Jul 8, 2011
1 parent be81d0e commit 8303b1cb8b7b117ec8f7511859a5f5c9fd4e7f74
Showing with 58 additions and 2 deletions.
  1. +58 −2 DCIntrospect/DCIntrospect.m
@@ -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);
}
@@ -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
@@ -63,6 +119,7 @@ + (DCIntrospect *)sharedIntrospector
sharedInstance = [[DCIntrospect alloc] init];
sharedInstance.keyboardBindingsOn = YES;
sharedInstance.showStatusBarOverlay = ![UIApplication sharedApplication].statusBarHidden;
+ [self workaroundUITextInputTraitsPropertiesBug];
}
#endif
return sharedInstance;
@@ -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];

0 comments on commit 8303b1c

Please sign in to comment.