With Swift 2.0 already out, most of the community is already familiar with the major new features, including reflection, error handling and Objective-C generics, which we’ve covered on our blog before. But the latest Swift version includes many other lesser-known functionalities, some of which I would like to discuss today.
With Swift 2.0 already out, most of the community is already familiar with the major new features, including reflection, error handling and Objective-C generics, which we’ve covered on our blog before. But the latest Swift version includes many other lesser-known functionalities, some of which I would like to discuss today. Without further ado, let’s start with...
Have you ever wondered why you can instantiate a Selector using
"string literals", or why you can use
[.Array, .Literals] to create option sets? Well, this is not some kind of compiler magic – Swift offers native, protocol-driven support for implementing such literal convertibles. Swift offers the following protocols:
Now, consider the following
You may use
StringLiteralConvertible to make it instantiable using only a string literal – I won’t tell you how, though! Consider it homework.
Now let’s pretend you’re developing a scientific application. You need an enum to represent a bit, which you then use to compose a string of zeroes and ones.
Not exactly what you were expecting, right? The reason behind this output is that because
Bit doesn’t conform to
Printable), the interpolation mechanism implicitly uses reflection to determine the string representation – and the default mirror produces just the name of a case.
Of course, you could make your type conform to
CustomStringConvertible and fix the issue, but where’s the fun in that? Let’s use another less well-known Swift protocol,
The main difference between
StringLiteralConvertible is that you don’t implement it on your type – instead, you need to extend
String by overloading
Hooray! That’s way better.
When Apple first revealed Swift, developers quickly came to the conclusion that it was created with interoperability in mind. Today we all know there are several ways to make your Swift code work with Objective-C and vice versa. Let’s review our options:
@objcattribute – we may explicitly mark whole classes, protocols or methods as visible to Objective-C.
And that’s basically it… or is it? Let’s examine the following code:
How in the name of Chris Lattner is the above code compiling? Well, after digging into Swift’s standard library, we notice that Array actually conforms to a mysterious protocol:
_ObjectiveCBridgeable. And here’s its interface:
Now you’re asking – what’s the proper way of implementing it and what are you gaining? This time, imagine you’re developing a geometry app and need to represent a point (without using CoreGeometry, obviously). Consider the following types:
Point conform to
_ObjectiveCBridgeable (you can see how in the attached slides or a demo playground), the following code actually compiles with no warnings whatsoever:
And that, ladies and gentlemen, is how all interoperable types in Swift are implemented.
These were only three of the many hidden functionalities in Swift. To search for such gems, I would recommend digging into Swift’s standard library, using LLDB type lookup, and, most importantly, experimenting in playgrounds over and over again.
The complete demo playground is available in my GitHub repository.
The code examples in this article were written as of Swift 2.0 and are subject to change in subsequent language releases.
This is an excerpt from my talk at the August 27th Mobile Warsaw meetup: "Hidden Gems in Swift" Check it out below: