Skip to content

Instantly share code, notes, and snippets.

@groue
Created March 8, 2011 23:21
Show Gist options
  • Save groue/861350 to your computer and use it in GitHub Desktop.
Save groue/861350 to your computer and use it in GitHub Desktop.
// helper function for silentValueForKey
id silentValueForUndefinedKey(id self, SEL _cmd, NSString *key) {
return nil;
}
// The purpose of this function is to have the same result as
// [object valueForKey:key], but instead of letting [NSObject valueForUndefinedKey:]
// raise an NSUndefinedKeyException, it silently returns nil instead.
id silentValueForKey(id object, NSString *key) {
// Does object provide the same implementations of valueForKey: and valueForUndefinedKey: as NSObject?
// If it does not, don't mess with it.
Class originalClass = [object class];
SEL vfukSelector = @selector(valueForUndefinedKey:);
SEL vfkSelector = @selector(valueForKey:);
if ((class_getMethodImplementation([NSObject class], vfukSelector) !=
class_getMethodImplementation(originalClass, vfukSelector))
||
(class_getMethodImplementation([NSObject class], vfkSelector) !=
class_getMethodImplementation(originalClass, vfkSelector)))
{
return [object valueForKey:key];
}
// Now the magic: let's temporarily switch object's class with a subclass
// whose implementation for valueForUndefinedKey: just returns nil.
const char *silentClassName = [[NSString stringWithFormat:@"GRMustacheSilent%@", originalClass] UTF8String];
Class silentClass = objc_lookUpClass(silentClassName);
if (silentClass == nil) {
silentClass = objc_allocateClassPair(originalClass, silentClassName, 0);
class_addMethod(silentClass, vfukSelector, (IMP)silentValueForUndefinedKey, "@@:@");
objc_registerClassPair(silentClass);
}
object->isa = silentClass;
// Silently call valueForKey!!!!
@try {
id value = [object valueForKey:key];
object->isa = originalClass;
return value;
}
@catch (NSException *exception) {
object->isa = originalClass;
[exception raise];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment