Posted by: bearc0025 | June 8, 2012

iOS Dynamic Method Resolution

Apple docs on Dynamic Method Resolution


If you want a class to respond to a given method w/o knowing what that method is when coding, you can use Dynamic Method Resolution.

In my case, I wanted to store some values in a dictionary not knowing what would be stored there (JSON parsed into a dictionary). Then have my class respond to getters/setters by looking for the given item as a key in the dictionary.

The answer here by Amy Worrall provides the bulk of the solution.

Basically you override resolveInstanceMethod: to call class_addMethod which adds accessorSetter or accessorGetter depending on the method being attempted.

+ (BOOL) resolveInstanceMethod:(SEL)aSEL
    NSString *method = NSStringFromSelector(aSEL);
    if ([method hasPrefix:@"set"])
        class_addMethod([self class], aSEL, (IMP) accessorSetter, "v@:@");
        return YES;
        class_addMethod([self class], aSEL, (IMP) accessorGetter, "@@:");
        return YES;
    return [super resolveInstanceMethod:aSEL];

Then implement those added methods, accessorSetter or accessorGetter, (I changed NSString to NSObject to allow for various class types to be stored in my dictionary. Also, for the setter, I remove ‘set’ and lowercase the next letter to turn something like setYikityBlar to yikityBlar)…

NSObject* accessorGetter(id self, SEL _cmd)
    NSString *method = NSStringFromSelector(_cmd);
    // Return the value of whatever key based on the method name
    return [((EventItem *)self)->valDict objectForKey:method];

void accessorSetter(id self, SEL _cmd, NSObject* newValue)
    NSString *method = NSStringFromSelector(_cmd);
    // remove set
    NSString *anID = [[method stringByReplacingCharactersInRange:NSMakeRange(0, 3) withString:@""] stringByReplacingOccurrencesOfString:@":" withString:@""];
    NSString *firstLowerChar = [[anID substringToIndex:1] lowercaseString];
    anID = [anID stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:firstLowerChar];
    // Set value of the key anID to newValue
    [((EventItem *)self)->valDict setValue:newValue forKey:anID];

ARC requires a bit more precision in the interface declaration – otherwise you get compile errors. There’s a couple things you should be able to do. If you actually have the item you want to dynamically create the getter/setters for, you can declare the methods to be dynamic (see link at the top of this post).

However, in my case, I don’t have them as properties (I set them in another class like a dictionary). So I declared the getters/setters in the header, but don’t implement them. I do get a compiler warning that my class’ implementation is incomplete. If anyone has a better solution, let me know.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s


%d bloggers like this: