Providing meaningful default values for empty or absence optionals via Nil-Or-Empty-Coalescing Operator (???)
Since I started to learn Swift, I absolutely fell in love with the concept of optionals. First I thought “Well, thats just like classes in Java. Either there is a value or its null.” but now I know better and I really enjoy how optionals improved my overall coding style.
However, in some situations, I really hate the amount of boilerplate I have to write for a simple task. For example in one of my UITableViews. They use the wonderful automatic sizing via auto layout.
My model class though has a optional String as the value which gets displayed in the tableview. So when I use
to assign the value, I sometimes end up with strange cells, which are almost not touchable because auto layout hides the label when the text is nil or empty.
To get around this issue, I have to unwrap the optional first and check if it is either nil or empty. In such a case I provide some meaning default value to let the user for example know, that the value he is looking for is currently not available.
Not so far in the past, I stumbled across the ?? operator (which is called Nil Coalescing Operator by the way) which lets you provide default values for optionals which are nil. But this does not solve the case where the optional is not nil but empty.
Since I don’t like to write the same code over and over again, only changing the syntax a little bit to reflect the variable name, I found there must be a better way.
Fortunately, we can easily extend Optional and implement a nice function to do that for us. We only have to write the unwrapping code once in an extension and we never have to touch it again.
If for some reason it has to change, we can conveniently change it in one place instead of going through our whole project — which could be really painful. So here it is:
Thats way better. A simple function which checks whether the value is nil or empty and uses the default value in such cases. But why should we constrain ourselves to String? Wouldn’t it be nice to make this a general function for all sorts of optionals?
I think yes and thats why I went one step further. Of course not every optional has a isEmpty property. Strings and Arrays have them but what would an empty Int look like?
Well thats an easy one to fix. We can just create a protocol with the isEmpty property. Then we can constrain our function to look for Optionals which implement the aforementioned protocol.
As you see, for String and Array, we don’t even need to implement something since these types already have the isEmpty property. Now lets implement our new achievement in a type which has no isEmpty property by default to see if it really behaves as we expect it (I mean, who trusts computers anyways?)
Woa, thats awesome. It really works. But if you are like me, then you are lazy. Probably even so lazy that typing “orWhenNilOrEmpty” is already to much effort, even with autocompletion.
When I realized just how lazy I am, I remembered the ?? operator. Did you know that in Swift, you can write your own operators? I stumbled across this just when I was working on the above code and it totally blew my mind.
For me it was one of those absolutely lucky accidents which let myself doubt that there is such a thing like coincidence. It was just to perfect. I had to try it immediately and this is what I came up with:
I call it the Nil-Or-Empty-Coalescing Operator and I just love it. I hope this little piece of helps you to write better code. For me coming up with it was a great learning experience.
On the way I improved my understanding of Optionals (before that I never cared about .some(wrapped) and .none, nor did I actually know about them), I improved my knowledge about protocol extensions and constraints and last but not least, I learned how to write custom operators.
My recommendation is, whenever you find yourself writing the same or very similar code more than twice, you should definitely investigate if there isn’t a better way of doing things.