Swift Type Conversions
In Swift, the native String
, Array
and Dictionary
types are implicitly bridged to the Foundation
classes NSString
, NSArray
and NSDictionary
. In practice, this means that any Cocoa API we call that takes a Foundation
class can take the corresponding Swift type (I don’t say class here, because in Swift, String
, Array
and Dictionary
are structs).
It turns out that like many other things in Swift, this isn’t some language magic that only Apple gets to use. We can also build such implicit bridges, thanks to an undocumented Swift feature: The __conversion
function.
Let’s say we want to build a Point
structure. We will be using it in a context that doesn’t involve Core Graphics, Sprite Kit or a similar framework that already uses CGPoint
. In addition, we want to build the struct in a modern way using new features idioms like generics and tuples. But, we also want to use our new struct with Core Graphics APIs sometimes so we can take advantage of all the convenience functions we implemented (This is a contrived example, because points are so simple, but bear with me).
struct Point {
let x: Double, y: Double
}
Let’s define the implicit bridging in an extension:
extension Point {
func __conversion() -> CGPoint {
return CGPoint(x: x, y: y)
}
}
Now it’s possible to pass a Point
to any method or function that takes a CGPoint
.
let p = Point(x: 1.0, y: 1.0)
CGPointApplyAffineTransform(p, CGAffineTransformMakeRotation(M_PI))
The extension can even be defined in a different file in the context where we want to use Point
as a CGPoint
.
We can also overload the __conversion
function and define many different conversions. Here’s one that destructures Point
into a (Double, Double)
tuple.
extension Point {
func __conversion() -> (Double, Double) {
return (x, y)
}
}
Now this works!
let (x, y) = p
I believe this will come in handy, especially when we start writing more and more Swift and we want to isolate non-Swift and/or legacy API calls and classes.