Ipphones

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Tuesday, 8 April 2008

You're Doing it Wrong! A Brief Discussion of Categories and the Cocoa Way

Posted on 12:25 by Unknown
Let's talk about a part of the Objective-C language that is somewhat unique: Categories. Well, not completely unique: the latest edition of C# has added something called Extension Methods, which is very similar, but it hasn't been around long enough to have really sunk into the collective psyche of .Net developers yet. Other than this recent addition to C# and the obscure language TOM, I don't personally know of any programming languages that have an equivalent to Objective-C categories. There probably are some floating out there, but the "biggie" languages in the world of object-oriented programming - Java, Ruby, Python, C++ - do not have an equivalent construct. 

Categories are über-cool, and almost universally underused by programmers new to Objective-C. Although I'm not a big fan of C# or .net, I have to give Microsoft kudos for recognizing awesomeness and incorporating it. Let's keep our fingers crossed that they use it as effectively as the NeXT and Apple engineers have in Cocoa.

A lot of people who come to Cocoa from other languages and read Apple's reference book on Objective-C  skim over the section on Categories, say "cool," and then move on. Heck, Apple's own Objective-C primer makes no mention of categories, which is just a shame, because Cocoa programmers use categories a lot. So, what are they, you ask?

Simply put, categories allow you to add methods to existing classes without subclassing them. You can't add instance variables (colloquially called "iVars" or "ivars" in the Cocoa world) or properties, but you can add both class and instance methods with impunity.

So why is this cool? Let's take an example, and look at the design choices available to us in Objective-C versus other languages. I'll use a real-world but very simple example here, but there are countless examples in a programmer's day-to-day life where categories can make your overall code base more elegant, many of which are more complex and more compelling than this one.

One of my current side projects is building two Cocoa-based NNTP clients (for accessing Usenet ): one for the Mac and the other for the iPhone. Now, NNTP servers expects date information to be passed into it in a very specific way - in the format specified in RFC 822. A date string for NNTP needs to look something like this:
08 Apr 2008 12:14:40 -0500
Formatting dates with Objective-C/Cocoa is relatively easy, so I can create a string in this format from an NSDate object relatively easily, by doing this:

NSString *dateString = [theDate descriptionWithCalendarFormat:@"%d %b %Y %H:%M:%S %z" timezone:nil locale:nil];
But where does this code go? Do I really want to put this code everywhere I need to use it? Well, maybe... like I said, this is a simple example for purposes of illustration, and not as compelling as many other real-world examples, but play along with me here, okay?

In an NNTP client, this same long line of code would probably need to be put into dozens or maybe even hundreds of places. But what if RFC822 were to change? Or what if, after using similar code in dozens of places, I realize that I have made a mistake? What a pain!

There are many ways of dealing with this problem in other languages. I could, for example, create a private static method or a function (depending on language)  that takes a date and returns a correctly formatted string. In C or any of its supersets, I could choose to create a preprocessor macro using #define to avoid having the same logic in multiple places. I could also choose to subclass NSDate and add a method in the subclass to return this method. In some cases, that might be appropriate, but in a strongly-typed language like C++ or Java, I probably don't want to do that just to get a single method because it would force a lot of type coercion and messiness into my code.

Without categories, subclassing might be a good choice in Objective-C because it is weakly-typed and could be done with minimal messiness. But we can do it with NO messiness thanks to categories. In Objective-C, I can simply add a method to the existing NSDate class to do what I need. Anywhere I need to use this new method, I just make sure to include the header file from my category. In my simple example, the category header file (.h) would look like this:
#import cocoa/cocoa.h
#import appkit/appkit.h
@interface NSDate(NNTP)

-(NSString *)rfc822DateString;
@end
and my implementation (.m) file would look like this:
#import "NSDate-NNTP.h"

@implementation NSDate(NNTP)
-(NSString *)rfc822DateString
{
return [self descriptionWithCalendarFormat:@"%d %b %Y %H:%M:%S %z" timeZone:nil locale:nil];
}
@end
Once I have this, anywhere I need a date formatted in this particular way, I simply call this new method right on the date object, like this:
NSString *dateString = [myDate rfc822DateString];
The result? Very readable and much shorter code, and it places the actual logic into a single place making it easy to maintain. 

If you want to see a more complex use of Objective-C categories, check out this this earlier blog posting where I showed how to add network socket support to the delivered NSFileHandle class.

Categories make it easier to stick with the overriding design philosphy used throughout Cocoa, and its presence allows the Application Kit and UI Kit to have much shallower class hierarchies than you find in other object-oriented application toolkits. If you're working in Cocoa/Objective-C, you really, really should get into the habit of using Categories whenever it makes sense. When does it make sense? Any time you think to yourself, "Gee, I wish the delivered class [X] had a method that does [Y]".

Email ThisBlogThis!Share to XShare to Facebook
Posted in Categories, iPHone, iPhone SDK, Object-Oriented Design, Objective-C | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • Strong Encryption for Cocoa / Cocoa Touch
    Please do not use this code! Instead, check out Jim Dovey's Common Crypto code from AQToolkit . AES is a strong encryption standard tha...
  • Texture Coordinate Arrays or Things Nobody Tells You
    For some reason, a lot of OpenGL stuff just isn't well documented. Yes, I read the Red Book chapter on texturing. It didn't have a s...
  • Dynamically adding class objects
    Okay, folks, the first draft of the book is done, and I have some breathing room until the chapters start coming back from the tech reviewer...
  • Web Services Fun
    Before we work more with libxml, let's talk about web services. Web services are a good practical application of XML and, it would seem ...
  • An OpenGL Project Template for Xcode
    I'm not a fan of the OpenGL ES Application project template that ships with the iPhone SDK. It's a pain in the ass to go in and dele...
  • Handling Double Taps
    Alright, since the NDA is down, let's celebrate by posting some information, shall we? One question that I see posted a lot by new iPhon...
  • Twittering iPhone Developer List
    Tim Haines, the developer of the excellent BurnBall game, has started a list of iPhone developers who use Twitter. The last time I checked,...
  • More on OpenGL and Normals
    In an earlier post I talked about surface normals in OpenGL. In writing the Wavefront OBJ loading class, I've learned far more about no...
  • OpenGL ES From the Ground Up, Part 1 Addendum: Alphabet Soup
    One problem with blog postings is that they are self-edited. For my postings here, I have no external technical review and no copy editing d...
  • Writing
    I'm pretty swamped with writing work at the moment. The book project is going pretty well, and I'm fortunate to have a very experien...

Categories

  • 3D Models
  • Ad Hoc Distribution
  • ADC
  • Address Book
  • Amazon
  • Anaglyphs
  • App Store
  • Apple
  • Apple DTS
  • Apple Store
  • Application Store
  • articles
  • Award
  • Background Processing
  • Barcodes
  • Beta
  • Blog
  • Blogger
  • Blogging
  • Blogs
  • Blogspot
  • Book project
  • Bug Reporting
  • Captain Obvious
  • Categories
  • Censorship
  • CFFoundation
  • CGAffineTransform
  • Clang Static Analyzer
  • Cocoa
  • Cocoa Touch
  • Code Reuse
  • Code Signing
  • Computer
  • conferences
  • Controller Classes
  • Core Animation
  • Daring Fireball
  • Database
  • Debugging
  • Defect
  • Delegates
  • Design Awards
  • Developer Certifications
  • Discussion Forums
  • Edit Mode
  • employment opportunities
  • Encryption
  • Enterprise
  • Errata
  • free code
  • Free software
  • Full Screen
  • Game Programming
  • Gestures
  • Getting Started
  • goof
  • Google Code
  • Google Maps
  • Gotcha
  • Help
  • HIG
  • HTTP PUT
  • Idiots
  • Idle Timer
  • Images
  • Instruments
  • Interface Builder
  • iPHone
  • iPhone Applications
  • iPhone Dev Center
  • iPhone Developers
  • iPhone OS 3.0
  • iPhone SDK
  • iPhone SDK PNG
  • iPhone Simulator
  • iPhoneSDK
  • iPod
  • Job Opportunities.
  • k
  • Key Value Observing
  • Keynote
  • KVO
  • Landscape Mode
  • Learn Cocoa
  • Learn Cocoa on the Mac
  • libxml
  • Licensing
  • Mac Developers
  • Mac OS X
  • Macworld Expo
  • Microsoft
  • NDA
  • NeHe
  • New Category
  • New Release
  • NSFileHandle
  • NSMutableArray
  • NSMutableURLRequest
  • NSXML
  • Object-Oriented Design
  • Objective-C
  • Open Source
  • OpenGL ES
  • Optimizations
  • Other blogs
  • Paired Arrays
  • Parsing
  • Particle Engine
  • Party
  • PeopleSoft
  • Performance
  • Persistence
  • Pink Screen of Death
  • Piracy
  • Pixar
  • Podcasts
  • Press Release WTF
  • Press Releases WTF
  • private APIs Google
  • Project Template
  • Properties
  • Random Numbers
  • Rant
  • Rejected
  • Resources
  • Responder Chain
  • REST
  • Reverse Engineering
  • Rumors
  • Runtime
  • Sample Code
  • Screencast
  • screenshot
  • Scroll Views
  • snippet
  • Snow Leopard.
  • SOAP
  • Sockets
  • Source
  • Splash Screen
  • SQLite
  • SQLitePersistentObjects
  • Steve Jobs
  • Steve-Note
  • Strings
  • Stupidity
  • Subversion
  • Table Views
  • Taps
  • Template
  • Tip
  • Tips
  • Tririga
  • tutorials
  • Twitter
  • UIAlertView
  • UIColor
  • UIImage
  • UIPickerView
  • UIScrollView
  • UITextField
  • UIView
  • UIWebView
  • Update
  • Utilities
  • UUID
  • Vacation
  • Version Control
  • Web Services
  • Writing
  • WTF
  • WWDC
  • Xcode
  • XML

Blog Archive

  • ►  2009 (141)
    • ►  May (14)
    • ►  April (30)
    • ►  March (48)
    • ►  February (26)
    • ►  January (23)
  • ▼  2008 (163)
    • ►  December (46)
    • ►  November (25)
    • ►  October (44)
    • ►  September (2)
    • ►  August (5)
    • ►  July (2)
    • ►  June (9)
    • ►  May (2)
    • ▼  April (11)
      • The Dangers of Beta
      • Web Services Fun
      • Simplifying libxml
      • Web Services Fun
      • Golden Ticket
      • WWDC
      • Idiocy Can Come with Many Letters After Its Name
      • The Root of All Evil: Introduction to Optimizing O...
      • SDK Beta 3 is Out
      • You're Doing it Wrong! A Brief Discussion of Categ...
      • Pink Screen of Death
    • ►  March (17)
Powered by Blogger.

About Me

Unknown
View my complete profile