Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a reverse "setValuesForKeysWithDictionary" - a makeDictionaryWithObjectProperties?

I parse some JSON from a web service, this gives me an NSDictionary, I use this dictionary to populated properties on a valueEntity of type NSObject by

[myObject setValuesForKeysWithDictionary:JSONDict];

(myObject has the same property names and types as the dictionary from the JSON parser)

name = name
count = count
startDate = startDate
etc..

Is there a way to go the other way, where I have an NSDictionary that I would like to have "filled" with the properties and their values from an my NSObject subclass. Like I suggest in the title, something along the lines of this:

one way

MyObject *myObject = [[MyObject alloc] init];
[myObject setValuesForKeysWithDictionary:JSONDict];

the other way around

NSMutableDictionary *dict = [myObject makeDictionaryWithObjectProperties];

The reason for this is that I have a valueEntity which, by protocol, my views all conform to, but I would like to populate an NSManagedObject with the values as well. So I thought that using the NSDictionary as an intermediate step I can get around having to do a category on my NSManagedObject that sets each property manually from the value on my object subclassing NSObject.

With a dictionary I can go:

[myManagedObject setValuesForKeysWithDictionary:dict];

I just can't get the dictionary representation back out once I done the above?

like image 935
RickiG Avatar asked Sep 14 '10 18:09

RickiG


3 Answers

Yep, the method is:

- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys

You pass in an array of keys representing the object properties that you're interested in, and get back a dictionary containing the property values.

The NSKeyValueCoding protocol defines a number of powerful and highly useful methods; it's a great thing to get familiar with.

http://developer.apple.com/library/ios/#documentation/cocoa/reference/foundation/Protocols/NSKeyValueCoding_Protocol/Reference/Reference.html

There's also a very valuable companion guide:

http://developer.apple.com/library/ios/documentation/cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html#//apple_ref/doc/uid/10000107i

like image 143
jlehr Avatar answered Oct 23 '22 01:10

jlehr


Do you really want to get all the properties? Often it doesn't make sense to get all the properties of an object as a dictionary. For example, if an NSManagedObject contains a relationship, do you want to get it too in the dictionary? If so, how do you want to represent it?

As jlehr said, it's better to feed a set of keys explicitly using dictionaryWithValuesForKeys:.

That said, using the dreaded Objective-C runtime, you can indeed implement makeDictionaryWithObjectProperties. Use class_getPropertyList and property_getName. I won't detail how to do that, because if you do follow this approach, you know what you're doing.

By the way, it's very dangerous for you to assign a JSON object returned from the Internet to an NSManagedObject using setValuesForKeysWithDictionary:. Because, if the JSON object happens to contain an additional key which you don't expect, your code can suddenly crash. So, don't do that.

Another comment: your pseudo-code

NSObject *myObject = [[NSObject alloc] init];
[myObject setValuesForKeysWithDictionary:JSONDict];

doesn't make much sense: yes you can call setValuesForKeysWithDictionary: against NSObject, but it will miserably fail, because you can't setValue:forKey: for any of the entries in JSONDict to a vanilla NSObject. I guess you know that, but I'd like to say that explicitly so that a novice who comes across this page won't be fooled.

like image 40
Yuji Avatar answered Oct 23 '22 02:10

Yuji


This guy here used some runtime magic to get all the properties declared on an object and got the dictionary without manually providing the property names.

And there'e also this nice github repo i found, They pretty much do the same trick, but in a nice package. They also have the ability to create a json or plist from an object.

like image 1
Alex Zak Avatar answered Oct 23 '22 01:10

Alex Zak