Swift Tip: Refactoring to Associated Values
We're in the process of rewriting our Swift Talk backend from Ruby to Swift. Rather than trying to get everything right straight away, we typically port things over by writing Swift code with a very similar structure to the Ruby code. We make sure that everything works as expected, and only then do we refactor the code to be more Swift-like.
As an example, on the Episode page we show the user one of four things:
-
"Become a subscriber to download episode videos."
-
"Re-downloading episodes doesn’t use any download credits."
-
"You have (creditsLeft) download credits left"
-
"No download credits left. You’ll get new credits at the next billing cycle."
In Ruby, the four cases were modeled as an enum, and we did the same in Swift:
enum DownloadStatus {
case notSubscribed
case reDownload
case canDownload
case noCredits
}
To generate the text above, we can write an extension on DownloadStatus
:
extension DownloadStatus {
func text(creditsLeft: Int) -> String {
switch self {
// ...
}
}
}
This works as expected, but after using it for a while we realized that passing on the creditsLeft
everywhere — from the database, to the "controller" layer, to the view, to this method — can be a little annoying. It's also a little annoying to make up a value for the notSubscribed
case. In fact, the only place where we need it is in the canDownload
case.
To remedy these annoyances, we refactored our DownloadStatus
enum to include an associated value:
enum DownloadStatus {
case notSubscribed
case reDownload
case canDownload(creditsLeft: Int)
case noCredits
}
With this in place, we don't have to pass on the creditsLeft
separately, we can include it directly in the canDownload
case. This also makes it possible to write text(creditsLeft:)
as a computed property text
:
var text: String {
switch self {
// ...
}
}
Changing our code to use associated values gives us clearer code, and more importantly, instead of passing two parameters around in multiple places we now embed the second parameter in the DownloadStatus
enum.
To learn more about enums, take a look at our books: Functional Swift shows how enums can help you write simpler code, and Advanced Swift gives a more in-depth account of how they function.
You can buy both books as part of the Swift Essentials bundle, with a little discount to say thank you. 🙏