Created
March 8, 2011 23:21
-
-
Save groue/861350 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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