Drive Time with the Swift Standard Library

The last week and a half or so, I’ve been driving up and down the East Coast. (Hello I-95, my old friend. I’m paying tolls on you again.)

My trip included attending the 90th birthday of a family member in Virginia, visiting my sister in NJ, visiting a friend in Delaware, and then celebrating the birthday of my friend Larry Noto in Maryland. I also did an open mic night at Larry’s music store Music Land and saw Larry’s stand-up act , opening for Jon Lovitz.

While driving, I was thinking about a little piece of an app I’m working on. I write an integer out into a URL as a string and then read the integer back in when I interpret the URL—nothing earth-shattering.

My thoughts turned to ways to make that URL shorter and a bit less ugly, with the premise that longer URLs are uglier URLs.

As I made my way down the road, it occurred to me, a hexadecimal string would certainly be more compact. But then, if base 16 is good, base 32 would be even better. Two characters in base 32 could represent 1024 values instead of 100 in base 10. Three characters could represent over 32K values instead of 1000.

So, in the end I was looking for:

  • Small encoding. A way to encode an integer as a string that uses as few characters as possible.
  • A ‘URL-ready’ string. The resulting string should need no further URL encoding for things like spaces.
  • Easy to implement. The minor improvement is not worth a lot of engineering effort to implement or maintain.

Enter the Swift Standard Library

One drawback of a road trip is the inability to write code or even peruse documentation while driving. After arriving at my destination, I did some poking around and found these in the standard library:

An initializer for Int: init?(_:, radix:)

And one for String: init(_:, radix:, capitalized:)

In both initializers, the radix has a default value of 10 but can handle everything from base 2 to base 36.

Base 36?

In this base 36 encoding, the digits 0-9 and the letters a-z are used in the string representation. The decimal number 35 is z, the decimal number 940 is q4.*

Using a radix of 36 gooses the values representable by a two character string up to 1296, and by three characters up to over 46K.

And, as it turns out, I was already using those initializers with the default parameters to encode and decode the integer.

I ended up factoring out those calls into a few extensions on URL and URLComponents, but, conceptually the answer was simply to move from:

let stringValue = String(integerValue)
let int = Int(stringValue) ?? "0"

to

let stringValue = String(integerValue, radix: 36)
let int = Int(stringValue, radix: 36) ?? "0"

So, the solution met all of my criteria. I updated the code in my hotel room.

The Old Coldness

Checking on swiftdoc.org, it looks like this functionality has been in Swift since at least Swift 1.2.

This made me realize the even with all of the new things introduced with each release, Swift and the standard library had a lot of nice functionality from the beginning.

Some of my drive time thinking was about solving a programming problem. But then afterwards, my thoughts progressed to how we are understandably drawn to the brand new features, but that sometimes a piece of API that has been around for years can be brand new to you, and that’s just as exciting and delightful a discovery. •


* The encoding strategy in these standard library methods extend the encoding pattern used by hexadecimal numbers. Note that there are many different ways to encode digits or byte values, including Base32 described by RFC 4648.

A Generic Swift Blog Post

I began investigating SwiftUI to see if it is indeed the shortest path to a great app. Since then, I committed an update to the MemeMaker project that makes the initial interface a list of examples. I was experimenting with passing a different View into each row as the destination of the row’s NavigationButton, rather than hard-coding the destination.

I found that you can’t just make a property of type View. I believe that is because it uses Self within its declaration of the body property. And so the compiler dutifully complained.

Seeing the type-erasing AnyView type in the documentation, I wrapped everything in AnyViews to get it all working.

I got some feedback from Matt Ricketson on Twitter suggesting I use generics here instead.

Of course it makes complete sense, with better code and less code. You can see the diff here.

With the SwiftUI and Combine frameworks using generics so heavily, I need to develop my intuition about generics beyond arrays and dictionaries. I also really need get better at reading declarations that are chock full of generics.

Fortunately, I think the two go hand in hand.

When Swift first arrived, I found reading optionals in code to be difficult. But AppKit and UIKit development meant using them immediately. I dug in to understand them as best I could. I even wrote a song about it. And now reading and writing code with question marks and exclamation points seems natural, not baffling.

I’m hopeful that as I use SwiftUI and Combine that I’ll refine how I think about generics as well.

I’m also curious. Are there ways that you think about genetics that have made them more understandable for you? (Not so much the syntax, more so the zen of generics) Any articles that you’ve found particularly useful?

I’d love to hear. Please send any of your generic thoughts or thoughts on genetics to @jamesdempsey at Micro.blog or Twitter.

Also, if you are ever writing about generics on an iPhone: BEWARE! Autocorrect really wants to replace ‘generics’ with ‘genetics’! •