views:

513

answers:

5

I like the plist serialization capability for small collections of objects: it is simple, the storage is XML, etc. But I find setting values in dictionaries cumbersome:

[myDict setObject:keepThis forKey:@"ivar"];

I'd much prefer to use object derived of classes (or even just structs):

myObj.ivar = keepThis

... and then send a message to a collection to get a plist. The classes/structs used for this purpose could be restricted so that they map directly and easily to plist primitives; for example myObj could be mapped to a NSDictionary and a requirement could be placed on ivars such that they are one of the plist primitives.

Has someone already built a facility for this, or should I roll my own?

+5  A: 

I'm not sure that this is quite what you're talking about, but Key Value Coding will, among many other things, let you get a dictionary with values from an instance's data, and also set instance data from a dictionary.

There's also a way to ask an instance for a list of its attributes, though it turns out that you have to write some code yourself to make that work. (You, could, though, use the runtime introspection to implement that, if you wanted.)

(The NSCoding protocol is another way of letting your objects store/restore themselves, but the storage is binary, not XML, and you are still responsible for getting/putting each value you care about when asked by the system to do so.)

Sixten Otto
Another thing to keep in mind is that property list serialization kills the identity of the object(s) you serialize. If you need to maintain that identity, use `NSCoding` with `NSKeyedArchiver`, etc.
Marc W
But ... to "get a dictionary with values from an instance's data", you need to have an object that implements the informal protocol NSKeyValueCoding. For example, NSManagedObject does not implement this message of that protocol. So again, one is back to runtime introspection, or perhaps using the entity class of Core Data to pick the object apart. Also, NSCoding seems very manual, in that for every property you add to a class, you then need to go and edit the encoder and decoder - even when the en/decoders are keyed! So it looks like such a framework is just not out there...
jeff7091
`NSManagedObject` definitely implements `-dictionaryWithKeysForValues:`. In general, Core Data builds extensively on Key-Value Coding and Key-Value Observing to do its work.
Sixten Otto
Do you mean -committedValuesForKeys: ?
jeff7091
No, I mean `-dictionaryWithKeysForValues:`, the KVC method I linked to in my answer, and that you said in your earlier comment `NSManagedObject` doesn't implement. It does (along with much more of KVC and KVO).
Sixten Otto
No, you mean dictionaryWithValuesForKeys :-)
jeff7091
OK, you got me that time. :-)
Sixten Otto
Thanks for the help!!!
jeff7091
A: 

An interesting project. The Objective-C 2.0 Programming Guide has a section on the runtime functions to dynamically get a list of a class's properties:

objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)

With this, it should be quite easy to write a category on NSObject with a method that gets the list of properties and puts them into a dictionary.

Ole Begemann
The SO question that nall links ( http://stackoverflow.com/questions/1631358/is-there-a-way-to-dynamically-determine-ivars-of-a-class-at-runtime-in-cocoa-co/1631611#1631611 ) to contains code that provides the same end result.
Alex Reynolds
+2  A: 

You might want to check out this SO question which discusses putting an instance's ivars in a dictionary at runtime.

nall
A: 

In order to use properties for this, you would need to have a predefined set of possible keys. You can't use arbitrary names with the dot-syntax — it had to be a known property or accessor of the first operand. So there can't be a generic form of this. But if you do make one of your own, turning into a dictionary is as simple as doing [self dictionaryWithValuesForKeys:listOfProperties].

Chuck
As Ole Begemann pointed out, you can ask the runtime for a list of the properties for a class. NSObject also defines attributeKeys (though you do have to write the NSClassDescription that powers that, ultimately).
Sixten Otto
A: 

I saw this posted elsewhere, but it is exactly what I was looking for. The answers above point to the raw ingredients, but here it is, all wrapped-up: http://retaincount.com/blog/?p=7

jeff7091
So, just to be clear, if this is your answer now. KVC (and `-dictionaryWithValuesForKeys:`) *does* work on these objects? Since that's a big part of how this linked solution works....
Sixten Otto
Before I found this link, I wrote something that would work with CD. I ended up sending -attributesByName to the entity associated with the NSManagedObject instance; it works fine.As I had to write something (and it works), I haven't gone over to this package. But I will look at it for then next project.
jeff7091