Dec 2010

Simplify your models with SMModelObject

Check out SMModelObject on Github.

For almost every app we’ve made, I find myself writing “model classes” to store structured data and logic. For instance, when you search for a book in the Barnes & Noble app, we fetch book results from an XML-based API and parse the XML into Cocoa objects that get passed around to our Controllers and Views.

Pretty standard stuff. Now, one way to represent this data in memory would be to use anonymous NSArray+NSDictionary structures, like so:

I don’t know about you, but I cringe when I look at that code. So verbose, hard to read, no refactoring, no code completion; but most importantly, no type safety. I might write @"pric" by mistake somewhere else and waste an hour debugging.

So let’s write a “model class” to store Books in a typesafe way.

Again, very standard. Now we can create these typesafe objects and access their properties directly:

So, ahhh, much better.

But, man, that Book class seems like a lot of wasteful typing. Every property has to be written up to four times: declare instance var, write property, write @synthesize, and release in -dealloc if necessary.

Seems manageable until you start dealing with real-life objects. In the Barnes & Noble app, Books have twenty-one properties. And Book is just one of a couple dozen model classes in the app. Sigh.

Now, it turns out that ObjC has gotten better over the years, and as of the latest iOS SDK (4.2), LLVM+Clang can create your instance variables automatically and now write your @synthesize for you as well. This is really nice!

Leveraging this feature, our Book class now looks like:

Which is great, but we can do even better. Objective-C makes it easy to introspect classes at runtime, so we’ve created a simple base class called SMModelObject.

Using runtime introspection, SMModelObject can do lots of great stuff for free:

  • Automatic release of properties in -dealloc
  • Automatic implementation of NSCopying
  • Automatic implementation of NSCoding so you can archive/unarchive your model objects to disk for state saving or for the clipboard
  • Automatic -isEqual and -hash implementation to compare model objects by value

Now our Book class looks like this:

SMModelObject even overrides -description to print nicely-indented model object hierarchies for easy debugging.

Kickass.

EDIT 3/26/2011: This article used to demonstrate a feature of the Clang compiler that was experimental at the time: automatically writing @synthesize statements for you. It was awesome, but Apple decided it wasn’t finished and so the official Xcode release doesn’t contain it. I’ll update this article again once it’s released.

EDIT 8/29/2012: Xcode 4.4 now includes the LLVM 4.0 compiler which automatically @synthesizes properties as promised! It’s pretty much awesome. I’ve updated the article to demonstrate the niceness again.


This all started when André Pang wrote an amazing model base class called RMModelObject a few years back that is incredibly sophisticated and provides these same great features on the legacy ObjC runtime. RMModelObject was the inspiration for my class, which was much easier to write since ObjC 2.0 does all the heavy lifting.

We’ve historically used RMModelObject for all our model classes, so I must give full credit to André for this wonderful concept, and for saving me many extra hours of typing over the years.

Notes

  1. prowthish-istoselidon reblogged this from nfarina
  2. metalkin reblogged this from nfarina
  3. nfarina posted this