Creating Convenience Methods Using Categories in Objective-C

I’m working on my first iOS app. I’m new to objective-c, and one of the first things that struck me about the language was how low-level it felt. I’m accustomed to the polish and syntactic sugar of languages like Ruby and C#. Recently I needed to compare two NSDecimalNumbers. I realized that I couldn’t use >, =, or < operators, so I looked for comparison methods, which got me this for a greater-than comparison:

[myDecimalNumber compare:decimalNumber] == NSOrderedDescending

Oh God. Ugly. Unreadable.

Every time I wrote code like this I had to stop and think, “Greater-than. Does that need to equal NSOrderedDescending or NSOrderedAscending?” Code that reads like this is a mental stumbling block.

It would be great to have more human-readable methods to compare values. I’d like to write:

[myDecimalNumber isGreaterThan:otherDecimalNumber];

Ah, nice. Human readable, “my decimal number is greater than this other decimal number. Yes or no?”.

As it turns out, it’s pretty simple to do. In objective-c you can re-open and extend classes using “categories.” So I can add isGreaterThan and isLessThan methods to the NSDecimalNumber class by creating a category like this.

Header file: NSDecimalNumber+convenience.h

#import <Foundation/Foundation.h>

@interface NSDecimalNumber (convenience)
- (BOOL) isLessThan:(NSNumber *)decimalNumber;
- (BOOL) isGreaterThan:(NSNumber *)decimalNumber;
@end

Implementation: NSDecimalNumber+convenience.m

#import "NSDecimalNumber+convenience.h"

@implementation NSDecimalNumber (convenience)

- (BOOL) isLessThan:(NSNumber *)decimalNumber {
  return [self compare:decimalNumber] == NSOrderedAscending;
}

- (BOOL) isGreaterThan:(NSNumber *)decimalNumber {
  return [self compare:decimalNumber] == NSOrderedDescending;
}

@end

A category is declared just like an interface, only you use the name of the class that you want to extend for the class name and you add a category name in parenthesis after it. In this example I used “convenience” for the category name since I am just adding some convenience methods.

Voila. Import the header file into one of your classes, and you can call isGreaterThan or isLessThan on any NSDecimalNumber to get a true or false value. If you’re unfamiliar with Objective-C categories, check out Apple’s documentation. It’s pretty straight forward.

comments powered by Disqus