1

This is something I have been playing with, and have yet to make my mind up about.

When querying a database, it is extremely common that you will use the data in the response to create custom model objects. Let's use 'Book' as an example.

I have received JSON describing multiple Book objects. I parse the JSON into an NSArray of NSDictionarys. I now have a few options:

  • Make all properties on Book mutable (I hate this option). You could then have a BookManager class with takes an NSArray of NSDictionarys and maps the data in the dictionary to the correct properties.

  • Add an initialiser to the Book object which accepts the important details.

Example:

- (instancetype)initWithTitle:(NSString *)title author:(NSString *)author publishDate:(NSDate *)publishDate;

The aforementioned BookManager class could then take the NSDictionarys as before, but create the Book objects with this initialiser. This is nice, because you could then make all of the public facing properties on Book readonly. However, it is very limited, and if (as is often the case) there are a lot of properties on the model, this is not feasible.

  • Add an initialiser to Book which accepts the NSDictionary representation of itself. I dislike this approach in one way because I feel the responsibility is not the model's to create itself from a dictionary. I prefer the idea of a manager class mapping the dictionary to the model. However, I do like the fact that it means that all properties can be readonly.

There is no doubt in my mind I am missing other options, and if you are aware of them, please point them out. The aim of this question is to finally determine the best way to approach this scenario.

Infinity James
  • 4,667
  • 5
  • 23
  • 36
  • http://stackoverflow.com/questions/5873776/using-nsmutabledictionary-as-backing-store-for-properties – Grady Player May 19 '14 at 15:15
  • For the general case I prefer an init method that accepts a dictionary. This scheme is quite flexible, it "cascades" naturally when you have a superclass or inner dictionaries with sub-objects, and you can if you wish use a common core that makes use of KVC to do some of the inits. (Hint, use a mutable dictionary and remove keys as you "consume" them. Then whatever's left can be consumed by the "common core".) – Hot Licks May 19 '14 at 15:37
  • Look into Mantle - might be easier and more generic https://github.com/Mantle/Mantle/blob/master/Mantle/MTLManagedObjectAdapter.h – Sash Zats May 19 '14 at 16:03

2 Answers2

1

I regularly use an init method with the important arguments, but yes, it becomes very unwieldily when the number of arguments reach double digits and/or several of the arguments can be nil. The longest such method I have seen in the iOS SDK is CLLocation's

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate
                altitude:(CLLocationDistance)altitude
      horizontalAccuracy:(CLLocationAccuracy)hAccuracy
        verticalAccuracy:(CLLocationAccuracy)vAccuracy
                  course:(CLLocationDirection)course
                   speed:(CLLocationSpeed)speed
               timestamp:(NSDate *)timestamp

Regarding your last option, adding an initWithDictionary: method to Book could be expanded to also include a class-level method for creating instances of Book from an NSDictionary.

+ (instancetype)bookWithDictionary:(NSDictionary *)dictionary

And optionally a convenient way to get a dictionary representation from a Book instance.

- (NSDictionary *)dictionaryRepresentation

If you search the iOS documentation for "withDictionary" and "dictionaryRepresentation" you will see a few places where this is used. In other SDKs, you will sometimes see the method named as someObjectFromDictionary:

Jamie McDaniel
  • 1,809
  • 19
  • 15
  • The unfortunate part of this pattern is you move all of the verbosity you would have reserved for the arguments of the function to a bunch of strings. Compound that with ambiguous types in a dictionary and you kind of wind up right back where you started, but with even less type safety than before. – CodaFi May 19 '14 at 16:47
0

I think u can do this using JSONModel

see this

http://code.tutsplus.com/tutorials/getting-started-with-jsonmodel--cms-19840 https://github.com/icanzilb/JSONModel

ChandreshKanetiya
  • 2,414
  • 5
  • 27
  • 41