November 24 2009
Cocoa Tip: Extend NSNumber
by Brian Dunagan
As I mentioned in my last post, categories are such a nice addition to Objective-C. They allow me to wrap up new functionality in a standard class without subclassing it myself. Below, I extend NSNumber with two handy methods for printing out numbers and bytes in a human-readable version, turning 1,000,000 into 1 M and 976.6 KB, respectively.
@implementation NSNumber ( Utilities )
- ( NSString * ) humanReadableBase10 {
if ( self == nil ) return nil ;
NSNumberFormatter * formatter = [[ NSNumberFormatter alloc ] init ];
[ formatter setNumberStyle : NSNumberFormatterDecimalStyle ];
[ formatter setMaximumFractionDigits : 1 ];
NSString * formattedString = nil ;
uint64_t size = [ self unsignedLongLongValue ];
if ( size < 1000 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size ]];
formattedString = [ NSString stringWithFormat : @"%@ B" , formattedNumber ];
}
else if ( size < 1000 * 1000 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1000 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ KB" , formattedNumber ];
}
else if ( size < 1000 * 1000 * 1000 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1000 . 0 / 1000 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ MB" , formattedNumber ];
}
else {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1000 . 0 / 1000 . 0 / 1000 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ GB" , formattedNumber ];
}
[ formatter release ];
return formattedString ;
}
- ( NSString * ) humanReadableBase2 {
if ( self == nil )
return nil ;
NSNumberFormatter * formatter = [[ NSNumberFormatter alloc ] init ];
[ formatter setNumberStyle : NSNumberFormatterDecimalStyle ];
[ formatter setMaximumFractionDigits : 1 ];
NSString * formattedString = nil ;
uint64_t size = [ self unsignedLongLongValue ];
if ( size < 1024 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size ]];
formattedString = [ NSString stringWithFormat : @"%@ B" , formattedNumber ];
}
else if ( size < 1024 * 1024 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1024 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ KB" , formattedNumber ];
}
else if ( size < 1024 * 1024 * 1024 ) {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1024 . 0 / 1024 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ MB" , formattedNumber ];
}
else {
NSString * formattedNumber = [ formatter stringFromNumber :[ NSNumber numberWithFloat : size / 1024 . 0 / 1024 . 0 / 1024 . 0 ]];
formattedString = [ NSString stringWithFormat : @"%@ GB" , formattedNumber ];
}
[ formatter release ];
return formattedString ;
}
@end
UPDATE : I changed the method names to humanReadableBase2 and humanReadableBase10 per Sean’s point.