Writing Better Code with Custom Subscripts in Swift

As my first project of the year, I’m working on the Swift version of @catehstn’s iOS Unit Testing Workshopย – you canย sign up here if you’re interested.

One of the big benefits of testing is that you end up with a much better code design. Including using custom subscripts in Swift!

I’m working on a Tic Tac Toe game, so I have a board object:

As I was testing the initialization of my Board – to make sure all positions are indeed empty, I ended up with this test:

The way I had to get the position on a board looked super ugly and unnatural to me. I wanted it to be let position = board[row][column] instead. Thankfully, this more intuitive interface can be done very easily in Swift with custom subscripts!

So now, I access the positions from my tests in a much more intuitive way:

By adding a test to my complex initializer, I was able to experience (aka dogfood) the interface I was creating, forcing me to make it better designed right away. So when you do write tests, pay close attention to how it feels to use your own functions, and change them if they don’t make intuitive sense.


As I was writing a test for another method, I realized that both row and column should be grouped together. After all, I don’t really have a need for a column array. My real intention with the subscript was to get the position on the board. So I updated my subscript to this:

Now, my test is just:

But this was not good enough. In my other test, I needed to get the row and column from the possible list of row and column values:

I really hated having to use the rawValue for my rows and columns – that just looks ugly again! So I created another subscript:

Now my new test is nice and clean!

In fact, I’m going to delete the subscript that gets the position via the Int version or row and column. Using the enum values is much safer for my code! My initial test is now:

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.