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

  • Making OpenGL ES Screenshot
    The Bit-101 Blog has an entry that shows how to take a screenshot when using OpenGL ES . I tested this in my much-delayed particle-generato...
  • Adding CLANG to Your Build Process
    Frasier Spiers has a nifty piece this morning on using Git pre-commit hooks to automatically run the CLANG Static Analyzer. I'm not a G...
  • CLANG Static Analyzer
    If you aren't using the LLVM/Clang Static Analyzer , you really should be. The Clang Project is an attempt to write a front end for the...
  • A Little Help
    I'm having a problem with OpenGL ES, and it's keeping me from finishing my particle engine post. I was hoping someone here could see...
  • WWDC Accommodations
    Staying downtown in San Francisco is very expensive in the summertime. Bu, if you're going to WWDC, you really want to stay downtown. Yo...
  • Xcode File Templates and a Mystery
    One of the things that confuses many newcomers to Xcode is how to set it up so that your company name gets automatically filled in when you ...
  • Brain Surgery?
    Craig Hockenberry has an interesting post on his blog today about the iPhone background processing issue. Craig speaks from personal experi...
  • Book's Almost Done
    I just finished Chapter 16. I'll give it another read-over in the morning then it will go off to my writing partner for his review, then...
  • iPhone Alley
    Looks like Dave and I are going to make an appearance on the iPhone Alley Podcast next week. We're recording on Sunday night, so I woul...
  • Shuffling Arrays
    Ever want to randomize an array of items? It's a task that, for some reason, I've had to do a lot in recent programs. So, I wrote a ...

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