Data Modeling With MoltenCore

Introduction

Apple Provides Core Data to help facilitate Data Modeling, and I admit its pretty good, but I feel sometimes its not well suited for webservices, and it doesn't support JSON data at all. However MoltenCore can handle JSON data and XML Data seamlessly. Its built around apples KVC paradigm. Don't know what KVC is? Its okay grab a cup of coffee, and head over to: Key Value Codeing Programming Guide. Its Okay I'll wait...

Back? Okay good lets begin. In addition to what I support is the ability to take an entire tree or graph of data models and have them automatically created, including sub-objects! Before we begin I want to give you a few definitions used throughout this document.

Definitions

: This represents a property in your data model any time you see this, you should replace it with the property name you are working with, Ensuring the first letter is Capitalized.

: This represents the class that is used to implement a sub-object in your data models.

The Basics

To create your data models, first select the underlying technology you want to use, JSON or XML. Once you have selected this you simply need to subclass the appropriate Data Modeling Base class.

JSON

For JSON You want to subclass MVSJSONDataModel The default init method for JSON Data Models is:

- (id)initWithDictionary:(NSDictionary *)dictionary;

if its just a normal object or if the object is a list of other objects use:

- (id)initWithArray:(NSArray *)array;

XML

For XML You want to subclass MVSXMLDataModel The default init method for XML Data Models is:

- (id)initWithXMLElement:(NSXMLNode *)node;

Once you've created your sub classes you just need to added your data objects. And here apple will do almost all the work for us. In fact there is a good chance you are already doing it now. Simply add instance variables for all of your properties and use @property to declare them as a property and then use @synthesize to fill in the missing methods. I recommend marking all your properties as copy so that all the memory from the original objects get freed up quickly once your data models are instantiated.

A couple of notes, for XML Data models all of your properties need to be strings. Sorry to say but apple only supports going from objects to strings for XML Nodes and not the other way around. But luckily for us JSON has all that kind of stuff built into the spec. and most JSON decoders (SBJSON, and JSONKit, included with MoltenCore) will translate to native ObjC types. The only exception is dates.

The tricky part comes when you start using it with trees or graphs of data models, which is pretty much the entire reason for wanting to use this part of MoltenCore. To support automatically populating sub-objects I've taken a few liberties on apples behalf and added some extensions to KVC. See the next section for the details of these extensions.

Extensions to KVC

One of the biggest problems I had when I was developing my data modeling system for MoltenCore was making sure I didn't conflict with Apple's original KVC concepts. So much of what I did I did in extension to it. Needless to say there are some things that need to be explained.

JSON

Lists

If you do not want any transformations on the array, you can just ignore it and follow proper KVC Procedures implementing:

- (void)set<Key>:(NSArray *)anArray;
- (NSArray *)<Key>;

But if you want your data models to transform the data in the array do the following:

Just make sure that your property is a NSMutableArray. This is important.

Then just simply implement the following two methods:

- (void)insertObject:(id)anObject in<Key>AtIndex:(NSInteger)index;

This method gets called for each object in the array that was passed into the init method. This gives you a chance to transform anObject into another data model.

- (void)removeObjectFrom<Key>AtIndex:(NSInteger)index;

This method just removes the specified object at index from the array. This is required by Apple.

Dictionaries

Dictionaries are a pain. I just want to put that out there before I go much further. With that being said there are a few things you need to think about in respect to the data:

  • Do I want the data to be left as an NSDictionary?
  • Do I need the dictitionary to be translated into a new Data Model?
  • Do I want the data to be treated as a dictionary but transform the data in the dictionary before inserting it in?

The first two are pretty easy, where as the last one is hard. Luckily my code will figure out what you want to do and handle it for you.

If you want to dictionary to be left as is, you just need to create a typical set and get methods as per KVC.

- (void)set<Key>:(NSDictionary *)aDictionary;
- (NSDictionary *)<Key>;

However if you want to transform the object you need to provide the following method:

- (void)setDictionaryValueFor<Key>:(NSDictionary *)aDictionary;

Now for the complicated one, wanting a dictionary but having the values in the dictionary transformed. To Do this provide the following methods:

- (void)setObjectIn<Key>:(id)anObject forKey:(NSString *)key;

This Method sets the specified object in your dictionary for the key key.

- (void)removeObjectFrom<Key>ForKey:(NSString *)key;

This is required for set method to work. BOTH of these methods must be implemented for the set method to get called during init.

XML

For XML Data models for any sub-object you need to implement the following method:

- (void)setXMLElementValueFor<Key>:(NSXMLNode *)node;

Not implementing them will cause your code to crash at runtime with undefined selector errors. Don't say I didn't warn you.

In here this method basically all you need to do is:

- (void)setXMLElementValueFor<Key>:(NSXMLNode *)node {
        self-><key> = [[<KeyClass> alloc] initWithXMLElement:node];
}