Norm Barnard Mobile Software Consultancy

iOS app developer

(269) 301-0531

A little bit about my new app, Rainbow Fish

History

It was nearly two years ago that the idea for Rainbow Fish was born. I was walking to the coffee shop with my wife Amy, and she asks me "You know what would be really handy for me, an app that allows me to keep track of my colored pencils. Do you think you could make one for me?". Being a good husband and wanting a good reason to try out the new development language from Apple, Swift, I said "Sure!".

I started developing the app in earnest around February of 2015. Since I develop apps as my day job, many times the last thing I want to do when I get home as sit at my computer and do more work. As a result, it's taken far longer than I had anticipated to finally ship the app.

After many stops and starts, and after three major revisions to the Swift language, Rainbow Fish is finally available for download!

What is Rainbow Fish

Rainbow Fish is an app that allows colored pencil artists to easily track their inventory of colored pencils from their iPhone. Catalogs from several major pencil manufacturers such as Derwent, PrismaColor, and Faber-Castell are available from which you can search, browse and if it's a pencil you own, track it by adding it to your inventory. The app really becomes useful when you set a minimum on-hand amount as the app will place number badge on your inventory list for each pencil you have that's below that value. That way, when you're in the art supply store, you'll already know which pencils you need to pick up.

If this app seems useful to you, I would urge you to download a copy from the App Store. It's a free download and the app is free to use. I had fun making it, it's made my wife's life easier, and hopefully it helps you too!

† iPod Touch is also supported.

Displaying Byte Counts using NSByteCountFormatter

Let's assume for a moment that you're building an iOS or OSX application that requires you to display the sizes of some files that your application maintains. For example, you have an iPhone app that downloads some video and audio files and you need to present a view to your users that informs them of the sizes of those files so they can choose which files are using the most space on their iPhone and delete them.

Your first inclination may be to retrieve the attributes of each file that's been downloaded using NSFileManager.attributesOfItemAtPath(), look at the file size returned in the resulting Dictionary and start doing some division by various powers of two to return the size in gigabytes, megabytes, or kilobytes. I would suggest that you not do that. The engineers at Apple have already solved this problem and have provided us all with NSByteCountFormatter.

Using NSByteCountFormatter

NSByteCountFormatter takes all the drudgery out of calculating byte count sizes and returning them as standard human readable strings.

For example:

let size: Int64 = 1_234_567

NSByteCountFormatter.stringFromByteCount(size, countStyle: .File)
// returns "1.2 MB"

let biggerSize: Int64 = 1_234_567_890

NSByteCountFormatter.stringFromByteCount(biggerSize, countStyle: .File)
// returns 1.23 GB

From the Apple docs, there are four different enum values you can specify for countStyle:

- File
- Memory
- Decimal
- Binary

I would use File if you're displaying the sizes of a file on the file system, and Memory if displaying internal system RAM memory or some other non-file system representation of byte counts. If for some reason you don't want to use a power of two value to represent a memory unit (1000 = 1 KB) then you'll want to use the Decimal style in preference to Binary. Personally, I'm not sure why you would, but hey, I don't know your use case.

NSByteCountFormatter also provides you with quite a few configuration options to customize your output. Maybe you want to display the actual byte count along with the human readable value:

let size: Int64 = 4_678_543

let formatter = NSByteCountFormatter()
formatter.includesActualByteCount = true
formatter.stringFromByteCount(size)
// returns "4.7 MB (4,678,543 bytes)"

Maybe you need to only show sizes in Megabytes. You can configure an NSByteCountFormatter to only return those units:

let formatter = NSByteCountFormatter()
formatter.allowedUnits = .UseMB
formatter.stringFromByteCount(bigSize)

//returns "1,234.6 MB"

formatter.stringFromByteCount(5_976)

// returns "O MB"  !!

The last example is not very accurate and there doesn't appear to be any way to convince NSByteCountFormatter to show a fractional value in these cases, so you may want to permit display of units smaller than Megabytes.

formatter.allowedUnits = [.UseMB, .UseKB]
formatter.stringFromByteCount(5_976)

// returns "6 KB"

Conclusion

In addition to the simple examples I've provided here, you can specify more complex formatting options to NSByteCountFormatter. If you need more precise control over formatting your byte counts, read over the docs provided by Apple.

You needn't trouble yourself with performing integer division and string formatting to come up a presentable way to show your files sizes and byte counts. NSByteCountFormatter should be your new friend!

Click here to download a playground with my examples