Skip to content

Instantly share code, notes, and snippets.

@jakehawken
Last active July 3, 2016 04:28
Show Gist options
  • Save jakehawken/79d8d5d28546ace743bca4c8160f36b5 to your computer and use it in GitHub Desktop.
Save jakehawken/79d8d5d28546ace743bca4c8160f36b5 to your computer and use it in GitHub Desktop.
An auto-mapper for inflating custom data objects from a given NSDictionary. This is a highly dangerous / unsafe category on NSObject, mainly done just as a fun exercise to see if it could be done. Can't say I recommend you use it.
@implementation NSObject (DataMapping)
- (instancetype)initByAutoMappingFromDictionary:(NSDictionary *)dictionary
{
Class thisClass = [self class];
self = [thisClass init];
if (self)
{
[self mapDictionaryValues:dictionary];
}
return self;
}
- (void)mapDictionaryValues:(NSDictionary *)dictionary
{
NSArray *dictKeys = [dictionary allKeys];
for (NSString *key in dictKeys)
{
[self attemptToSetPropertyWithObject:dictionary[key] forKey:key];
}
}
#pragma - mark private / helper methods
- (void)attemptToSetPropertyWithObject:(NSObject *)object forKey:(NSString *)key
{
SEL selectorFromString = [self setterSelectorFromKeyString:key];
if ([self respondsToSelector:selectorFromString])
{
[self performSelector:selectorFromString withObject:object];
}
}
- (SEL)setterSelectorFromKeyString:(NSString *)inputString
{
NSString *capitalizedString = [inputString capitalizedString];
NSString *selectorString = [NSString stringWithFormat:@"set%@:", capitalizedString];
return NSSelectorFromString(selectorString);
}
@end
@jakehawken
Copy link
Author

This also works if you get rid of the init and expose the mapDictionaryValues method instead. Then you just use it as an instance method on an already initialized object.

@jakebromberg
Copy link

jakebromberg commented Jul 1, 2016

Shouldn't you call self = [super init] in your initializer? In fact, you don't want to call +alloc again because your object is already allocated.

@jakebromberg
Copy link

jakebromberg commented Jul 1, 2016

I see you're stripping out spaces. What is the goal of your method? Isn't the onus on the caller to provide valid inputs? There's a whole host of invalid characters (including the +[NSCharacterSet whitespaceCharacterSet]) the caller could provide. Are you sure accounting for these rules is something you want to take the burden of?

@jakehawken
Copy link
Author

Shouldn't you call self = [super init] in your initializer? In fact, you don't want to call +alloc again because your object is already allocated.

Very good point.

@jakehawken
Copy link
Author

I see you're stripping out spaces. What is the goal of your method? Isn't the onus on the caller to provide valid inputs? There's a whole host of invalid characters (including the +[NSCharacterSet whitespaceCharacterSet]) the caller could provide. Are you sure accounting for these rules is something you want to take the burden of?

Also a great point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment