New features in Swift 2

Swift 2

At the 2014 WWDC conference Apple announced Swift as a new language to write iOS app.  In February 2015 they released Swift 1.2, which fixed a lot of issues (especially with the compiler) and added new language features.

In June 2015 Apple announced at WWDC Swift 2, which will be made open source later this year.  In this post I will cover the new features in Swift 2.

New features in Swift 2

Println

If you want to write debug messages to the console, prior to Swift 2 you have probably used println("the message") a lot. In Swift 2, print now automatically prints a message on a new line. Hey … it’s all about the small things.

Enums

Enums are one of the 3 data structures in Swift and are a great way to hold a small set of data.  For example

enum OSXVersion {
    
    case Lion
    case MountainLion
    case Mavericks
    case Yosemite
    case ElCapitan
    
}

Because enums are in fact a data type, you can set a variable to be of type OSXVersion.

var myOS:OSXVersion = .Lion

But if you were to print out the value of myOS in Swift 1.2, you would end up with (EnumValue).

println(myOS) // Prints `(Enum Value)`

In Swift 2, enums now carry enough reflection to print out their value, which makes it more convenient then to print out the rawValue of an enum prior to Swift 2.

print(myOS) // Prints `Lion`

Repeat

The do-while loop has been renamed to repeat-while in Swift 2.

var i = 0

do {
    
    println(i)
    i++
    
} while( i < 10 )

In Swift 2 it looks like this

var i = 0

repeat {
    
    print(i)
    i++
    
} while( i < 10 )

Option sets

Option sets are a great update for NS_OPTIONS and simplify the usage of bitflags. They are used to easily pass multiple options within one variable by using bitewise operations, but with option sets you don’t really need to worry about setting bits.

To create an option set, all you have to do is create a struct which implements the OptionSetType protocol. The only requirement of this protocol is that your struct has a rawValue property.

struct FontOptions:OptionSetType {
    
    var rawValue:Int
    
}

Now you can just add the different options you want to provide as static constants.  Just make sure the rawValue of every option is a power of 2.

struct FontOptions:OptionSetType {
    
    var rawValue:Int
 
    static let StrikeThrough = FontOptions(rawValue: 1)
    static let Bold = FontOptions(rawValue: 2)
    static let Underline = FontOptions(rawValue: 4)

}

To use this OptionSetType, you just have to comma-seperate them in an array.

var style:FontOptions = []
style = [.StrikeThrough]
style = [.StrikeThrough, .Bold]

And if you want to check if a certain option was set, you can use the contains function.

if style.contains(.Bold) {
    // Set the style to bold
}

Guard

Guard is a new statement in Swift 2 which checks a condition and bails out if the condition is not met.  So what is exactly the difference between guard and an if statement?

Assume the following Swift 1.2 code where we have a createPerson function which can return a Person or a String (an error message for example).  As you can see we need to unwrap the dictionary and check for the values, if both values are correct we can create the Person object, otherwise we return an error message.

enum Either<A,B> {
    case Person(A)
    case Error(B)
}

struct Person {
    
    var name:String
    var age:Int
    
}

func createPerson( dictionary:AnyObject ) -> Either<Person, String> {
    
    if let name = dictionary["name"] as? String, let age = dictionary["age"] as? Int {
        
        return .Person(Person(name: name, age: age))
        
    }
    
    return .Error( "Could not create person" )
    
}

With the guard statement this code would look like this.

func createPerson( dictionary:AnyObject ) -> Either<Person, String> {
    
    guard   let name = dictionary["name"] as? String,
        let age = dictionary["age"] as? Int else {
    
        return .Error( "Could not create person" )
            
    }
    
    return .Person(Person(name: name, age: age))
    
}

Doesn’t this look a lot nicer?  We’re first checking if everything is OK, if not we do an early exit out of the function scope.  Otherwise we return a new Person object.  The nice thing with guard is that the unwrapped values name and age of the guard statement are also available in the fall-through.

Availability

I’m really excited about this new feature in Swift 2.  Apple finally made it easy to add SDK dependant code.

A common idiom we used was to use respondsToSelector with an if-statement.

if loginButton.respondsToSelector("doSomethingWithNewSDK") {
    
    // Do something
    
}

This is highly error prone, as we can make a typo in the selector its name.

In Swift 2 you can use the #available() directive.

if #available(iOS 9, *) {
    
    // Do something
    
}

Error handling

Swift 2 has some new ways on how to handle errors which removes some of the typical NSError boilerplate code.

Let’s say you want to ask a webservice for some data. Your code would probably look something like this.

func getNewsFromAPI() {

    service.getNews()
    
    // Do something after results are received
    
}

The problem is that service.getNews could fail, as there might not be an internet connection.  You could solve this by working with NSError, but then our code would suddenly look like this.

func getNewsFromAPI( inout error:NSError?) -> Bool {

    if( service.getNewsWithError(&error) ) {
     
        return false
    }
    
    // Do something after results are received
    
    return true
    
}

This works … but it adds a lot of boilerplate code.

In Swift 2, we can now use the try keyword.

func getNewsFromAPI() {

    try service.getNews()
    
    // Do something after results are received
    
}

Now we’ve indicated that the getNews() method can fail.  But how do we handle the error?

That’s pretty easy, we just have to indicate that the function can throw an exception.

func getNewsFromAPI() throws {

    try service.getNews()
    
    // Do something after results are received
    
}

If you want to handle the error you just wrap it inside a do-catch statement.

func getNewsFromAPI() throws {

    do {
        try service.getNews()
        
        // Do something after results are received
        
    } catch {
        
        // Handle error
        
    }
    
}

If the service.getNews method throws a specific error, you can pattern match it in the catch.

func getNewsFromAPI( ) throws {

    do {
        try service.getNews()
        
        // Do something after results are received
        
    }catch NewsError.NoInternetConnection{
        
        // Handle specific error
        
    }
    catch {
        
        // Handle error
        
    }
    
}

Defining your own error types

Apple made it really easy now to create your own error types. You just have to implement the ErrorType protocol on your class.

The easiest way is to use an enum to hold the data for related errors.  This is because enums allow to hold extra data in the form of a payload (via associated values), and the compiler handles protocol conformance detail automatically.

So for example, say you created a class which connects to an API, you could create an APIErrors enum, which groups the related errors that could happen when connecting to an API.

enum APIError : ErrorType {
    
    case NoInternetConnection
    case ServerDidNotRespond
    case RequestTimeOut
    
}

Now you can just throw the error like this

if( noInternet ){
    
    throw APIError.NoInternetConnection
    
}

Wrapping up

As you see there are a lot of nice new features in Swift 2. I hope this give you a bit more insight in what is coming up.

To learn more, check out the following sites: