5

I am trying to learn reflection in Objective-C. I've found some great information on how to dump the property list of a class, especially here, but I want to know if it is possible to set a property's value using reflection.

I have a dictionary of keys (property names) and values (all NSStrings). I want to use Reflection to get the property and then set its value to the value in my dictionary. Is this possible? Or am I dreaming?

This has nothing to do with the dictionary. I am merely using the dictionary to send in the values.

Like this question, but for Objective C.

- (void)populateProperty:(NSString *)value
{
    Class clazz = [self class];
    u_int count;

    objc_property_t* properties = class_copyPropertyList(clazz, &count);
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        NSString *prop = [NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
        // Here I have found my prop
        // How do I populate it with value passed in?
    }
    free(properties);

}
Community
  • 1
  • 1
Patricia
  • 5,019
  • 14
  • 72
  • 152

2 Answers2

13

Objective C properties automatically conform to the NSKeyValueCoding protocol. You can use setValue:forKey: to set any property value by a string property name.

NSDictionary * objectProperties = @{@"propertyName" : @"A value for property name",
                                    @"anotherPropertyName" : @"MOAR VALUE"};

//Assuming class has properties propertyName and anotherPropertyName
NSObject * object = [[NSObject alloc] init];

for (NSString * propertyName in objectProperties.allKeys)
{
    NSString * propertyValue = [objectProperties valueForKey:propertyName];

    [object setValue:propertyValue
              forKey:propertyName];
}
Fruity Geek
  • 7,351
  • 1
  • 32
  • 41
  • It is reflection. The property mutator and accessor is called when you use this method. – Fruity Geek Aug 28 '14 at 15:20
  • 3
    @Lucy [`setValue:forKey:`](https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/Protocols/NSKeyValueCoding_Protocol/Reference/Reference.html#//apple_ref/doc/uid/20000471-BABEHECF) is part of the `NSKeyValueCoding` protocol, which `NSObject` conforms to. It has nothing to do with dictionaries; you're thinking of `setObject:forKey:`, which is a method on `NSMutableDictionary`. – Dave DeLong Aug 28 '14 at 16:09
  • 1
    @Lucy `setValue:forKey:` jumps through a bunch of hoops, finds the setter, and calls it. It is reflection. And it is generally to be avoided. – bbum Aug 29 '14 at 20:50
3

The NSKeyValueCoding protocol, which NSObject implements (see NSKeyValueCoding.h), contains the method -setValuesForKeysWithDictionary:. This method takes exactly the kind of dictionary you describe and sets the appropriate properties (or ivars) of the reciever.

This is absolutely reflection; the code in setValuesForKeysWithDictionary: accesses the properties by the names you give it, and will even find the appropriate ivar if no setter method exists.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • 2
    This is reflection; just because you didn't write the reflective code doesn't mean that's not what it is. – jscs Aug 28 '14 at 18:46