BSByteFormatter
Language: Objective-C, Author: Michele Balistreri
License: Public domain
This is a formatter (NSFormatter subclass) which converts NSNumber instances representing mostly sizes in bytes and converts them to a human readable string (2048 => "2 KB"). It supports unit of measure up to the Terabyte. Note that input is assumed to be an NSNumber and no checks are performed about it.
BSByteFormatter source preview
#import "BSByteFormatter.h"
@implementation BSByteFormatter
- (NSString *)stringForObjectValue:(id)anObject
{
NSArray *sizeTable = [NSArray arrayWithObjects:@"B", @"KB", @"MB", @"GB", @"TB", nil];
int i;
float result = [anObject floatValue];
if([anObject respondsToSelector:@selector(length)])
{
return anObject;
}
for(i = 0; i < 5 && result >= 1024; i++)
{
result = result/1024;
}
if((float)(result - (int)result) > 0.01)
{
return [NSString localizedStringWithFormat:@"%.2f %@", result, [sizeTable objectAtIndex:i]];
}
else
{
return [NSString localizedStringWithFormat:@"%.0f %@", result, [sizeTable objectAtIndex:i]];
}
}
@end
BSByteFormatter header preview
#import <Cocoa/Cocoa.h>
@interface BSByteFormatter : NSFormatter
{
}
@end
Download Archive
Compatible with:
- Mac OS X 10.0
- Mac OS X 10.1
- Mac OS X 10.2
- Mac OS X 10.3
- Mac OS X 10.4 PPC
- Mac OS X 10.4 Intel
- Mac OS X 10.5 PPC
- Mac OS X 10.5 Intel

Perhaps too nit-picky, my DRY "code smell sense" suggests you replace that last if with something like the following, "hoisting out" the small difference in those two returns:
NSString *format;
if ((float) (result - (int) result) > 0.01)
format = @"%.2f %@";
else
format = @"%.0f %@";
return [NSString localizedStringWithFormat:format, result, [sizeTable objectAtIndex:i]];
Concise is always good. In my own adapted code, I took it a few steps further... My version accepts a string or an NSNumber, and does away with the counter variable. (The for-in loop works on 10.5 and higher.) Thanks for the ideas!
- (NSString*) stringForIntegerValue:(NSInteger)integerValue {
NSArray *suffixes = [NSArray arrayWithObjects:@"B", @"KB", @"MB", @"GB", @"TB", @"PB", nil];
float value = integerValue;
for (NSString *suffix in suffixes) {
if (value >= 1024) {
value /= 1024;
} else {
NSString *format = (value - (int)value >= 0.1) ? @"%.1f %@" : @"%.0f %@";
return [NSString localizedStringWithFormat:format, value, suffix];
}
}
}
- (NSString*) stringForObjectValue:(id)anObject {
return [self stringForIntegerValue:[anObject integerValue]];
}