WWDC15 offered us a lot of new stuff to digest, including a new version of our favorite Cocoa language, swift, which reaches version 2. Swift is evolving really quick, and I really love the changes and enhancements that are being added to it. We have even come to the point of adapting Objective-C and the good old Cocoa frameworks to Swift strongly typed nature. I would like to share my opinion on some of the last changes introduced in Swift 2.

Enums

Enums in swift are both powerful and intuitive, and with the last version of the language, they have been greatly improved. A nice addition is the additional reflexion intelligence that allows the language to dive into a variable to print a value for an Enum, so now if you have

enum Fruits {
   Apple, Strawberry, Banana, Kiwi
}

You can perform a user-friendly printing of a Fruit variable:

var tropicalFruit = Fruits.Kiwi
print(tropicalFruit) // prints Fruits.Kiwi

But even better is the fact that now you can have several types embedded in the Enum. This is really handy for returning values from a REST API call, like this:

Enum ServerResponse <String, NSError> {
   case Result(String)
   case Error(NSError)
}

For me this can be really useful for handling responses generically and being sure you can always handle the backend’s response in a coherent and unique way. Recursion has also been added to Swift, so now you can build recursive enum definitions. I find that could be interesting for building complex structures like hierarchical collections or mathematical expressions:

enum Fraction<Int> {
   case Number(Int)
   indirect case Division(Fraction, Fraction)
}

The new “DO” statement

Swift 2 introduces the “DO” statement as a way to isolate a scope from the rest of code surrounding it. What I really love about this addition is that it allows you to have a tighter control on variables memory usage and allocation. Now, you can define a do scope to perform some costly operations (whose results are not supposed to outlast this scope) and have some certainty that the memory will be properly (and safely) deallocated, i.e:

var result: ResultType?
do {
   for (var i = 0; i < 100000; i++) {
      var object = ReallyBigMemoryObject(...)
      // perform some operations on object and add to result.
      result = result + object.expensiveOperation()
   }
}
// use result

Because “do” was being used for the do-while loops, in order to avoid any ambiguity, do-while has been aptly renamed to repeat-while (which makes a lot more sense IMHO):

repeat {
   // perform some operations until while clause verifies.
} while (someCondition == false)

Option sets

Option sets have been greatly improved in both definition and usage. Previously, when you wanted to specify a set of options to, say, UIView.animateWithDuration(…), you had to concatenate them with a logical OR. Besides, the fact that a set of options could be nil added an artificial (IMHO) situation in which an empty set of options was indistinguishable from an undefined variable. Now option sets make more sense to me.

viewAnimationOptions = [.Repeat, .CurveEaseIn, .TransitionCurlUp] // instead of .A | .B | .C
viewAnimationOptions = [] // previously it was nil 
if viewAnimationOptions.contains(.Repeat) { ... } // instead of if viewAnimationOptions & .A != nil

Methods & Functions coherence

Previously, in Swift 1.X, a function and a method defined exactly the same will get invoked differently:

func myFuncWithInteger(myint: Int, string: String) {...}
class MyClass {
   func myFuncWithInteger(myint: Int, string: String) {...}
}
let myClassInstance = MyClass()
myFuncWithInteger(3, "hello world") // global function
myClassInstance.myFuncWithInteger(3, string: "hello world")

This different invocation system was incoherent, and I think it’s really nice that Apple addressed this in Swift 2:

myFuncWithInteger(3, string: "hello world") // global function
myClassInstance.myFuncWithInteger(3, string: "hello world")

Guard statements

One of the most recurring tasks I face when building Apps lately is parsing and analyzing data received from a backend, usually in JSON format. Swift 1.2 added the ability to unwrap a set of optionals at once, and that was really helpful, but we still have to face situations in which you needed to sequence the unwrapping in cascade for performance or convenience. Now the guard statement allows us to perform a “reverse if-let”, thus performing an action if we are not able to get the value in the variable:

func parseServerResponse(json: AnyObject) -> ParseUserResponse <User, NSError> {
   guard let username = json["username"] as? String else {
      return .Error(NSError(...))
   }
   guard let email = json["email"] as? String else {
      return .Error(NSError(...))
   }
   let user = User(name: username, email: email)
   return .User(user)
}

Single case pattern matching

A really useful and fast way of checking a value contained in an enum with a case-like syntax:

if case .MyEnum(let value) = functionToMatch() where value == "OK" { doAction(value) }

Conditions in for loops

Another nice addition, the ability to loop a collection of objects, but only those complying with a condition:

for value in myCollectionVariable where value > 5 { doSomething(value) }

Extensions for protocols

One of my favorite additions in the new version of Swift, and something I was really missing. This give us the chance to add extensions to protocols, including well known protocols such as CollectionType, Printable and Equatable. I think the possibilities are endless here. I could write a function, for example, that would return true if two collection types have most of their elements equals, or perform the same operations over different types of collections. Nice.

This also implies another beautiful change to the language. Now that protocols can have extensions, we no longer have to recur to global functions to be applied to collections, making more sense in an object oriented language like swift. So now instead of:

let x = filter(map(numbers) {$0 * 3}) { $0 >= 0 }

We have something more logical (and easy to read) like:

let x = numbers.map {$0 * 3}.filter{$0 >= 0}

Exception handling

Swift 2 includes exception handling through try-catch constructs like you can find in other languages (such as java). I’ve always thought that optionals were great in swift for managing error handling, so I’m not quite sure if I really need this exception catching mechanism. Anyway, I plan on looking into it in the future and introduce it in my projects to see if it makes sense and really helps me build better, most robust code without loosing readability or code flow:

func failableFunction() -> Bool {
   do {
      someMethodThatCanThrowAnException()
      return true
   } catch NSURLError.FileDoesNotExist {
      fatalError(...) // will exit the application like an Assertion.
   } catch let error {
      print("Error: \(error)")
      return false
   }
}

func anotherFailableFunction() throws -> AnyObject {
   methodThatCanThrowAnException()
}

Other improvements

Swift 2 comes with lots of other improvements, including enhanced debug messages, better integration for testing units, beautiful rich text for playgrounds’ docs, the #availability construct (allowing us to check if a method or property is available for a concrete version of the OS), etc.

Languages they are a changin’

As you can see, Swift 2 is a major new release loaded with lots of changes and improvements.

This is the first time in my life that I’m working with a language that’s actually evolving and growing regularly. When Swift 1.1 came out, including its first modifications, I thought it would be hard, or even disturbing, having to periodically adapt myself (and my projects) to changes in structure and API in the language, but today I find it’s actually cool. The language changes are mostly for the better, and I really appreciate being pushed outside of my comfort zone, constantly learning, and being witness of the evolution of a live language that grows thanks to the feedback of the developer community. I think it’s kind of democratizing the way we work and build things, and I like it.