bdunagan

Brian Dunagan

November 24 2009
Cocoa Tip: Extend NSNumber

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.

Cocoa Tip: Extend NSDate iPhone Tip: No NSHost
LinkedIn GitHub Email