views:

245

answers:

3

The object in question consists of key/value pairs aka @property. Is there an elegant way to encode/decode this object to a dictionary? It seems brute force to manually pull out each attribute and create the dictionary by hand.

+2  A: 

Objective-C's "object as dictionary" support comes through Key-Value Coding:

NSArray *myAttributes; // Assume this exists
NSDictionary *dictRepresentation = [object dictionaryWithValuesForKeys:myAttributes];
Chuck
Hmm is [object attributeKeys]; http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/nsobject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/attributeKeysnot available on iphone?
Keith Fitzgerald
I don't think it is. But it's of questionable use on OS X anyway — a class has to be specifically written to make it work right. Key-Value Coding lets you treat an object as a dictionary to some extent, but the Object == Dictionary equivalence isn't as strong as, say, Python or Javascript.
Chuck
You can partly hack it by using Objective-C runtime functions to get at the object's properties dynamically, but in most cases it's not worth the effort.
Chuck
+3  A: 

Does it absolutely need to be a dictionary? Because NSKeyedArchiver gives you the memento-stored-by-key behaviour without actually being an NSDictionary - and has the added bonus that it can archive many objects which property-list serialization doesn't automatically support. There's a good description of using archivers and unarchivers on the CocoaDev wiki.

Graham Lee
doesn't need to be a dictionary and you bring up an excellent point. i couldn't find an excellent example of nskeyedarchiver - can you link a blog or a snippet?
Keith Fitzgerald
check out the cocoadev link I added, or chapter 10 of Cocoa Programming for Mac OS X by Hillegass (3rd ed)
Graham Lee
+1  A: 

If the keys you desire are ObjC-2.0 properties of the class in question, you could do something similar to the following:

// Assume MyClass exists
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([myClassInstance class], &count);
NSMutableDictionary *propertiesDict = [NSMutableDictionary dictionary];
unsigned int i;
for(i = 0; i < count; ++i) {
  NSString *propertyName = [NSString stringWithCString:property_getName(properties[i]) encoding:NSASCIIStringEncoding];
  id propertyValue = [self valueForKey:propertyName];
  if(propertyValue)
    [propertiesDict setObject:propertyValue forKey:propertyName];
}
free(properties), properties = NULL;
// Do something with propertiesDict

This could also be a simple class extension.

sbooth