This is a text summary of the What’s new in Swift 2 video (Session 106) posted by Apple. This is a recording of a session at WWDC 2015. You can watch this video in Apple’s WWDC Page. Additionally, if you can’t view the video (because you don’t have an Apple device, etc), Apple has also posted this vid in their YouTube page.

This post covers everything important from the aforementioned video. I personally learn much better when I read instead of watching a video, so initially I was going to write this for myself, but nothing wrong in releasing it for everyone else, right?


Philosophies behind Swift 2:

  1. Refine language and tools fundamentals.
  2. Affordances for writing robust and safe code.
  3. Code Beauty

The video covers 5 aspects of Swift:

  1. Fundamentals
  2. Pattern Matching
  3. Availability Checking
  4. Protocol Extensions
  5. Error Handling

Fundamentals

Enums

Enums carry enough reflection information, that you can print them and they work great.

enum Animals {
	case Dog, Cat, Troll, Dragon
}

let a = Animals.Dragon
print(a)

Prints:

Animal.Dragon

Associated Values in Enums

They are the perfect model for discriminating union, great when you have two values of different values you want to store in one thing.

enum Either<T1, T2> {
	case First(T1)
	case Second(T2)
}

This didn’t work in previous versions of Swift.

Recursive Enums

enum Tree<T> {
	case Leaf(T)
	indirect case Node(Tree, Tree)
}

By using the “indirect” keyword where recursion happens, you are allowed to have recursive enums. This also works great with Pattern Matching.

Scoping

“do” Statement

do {
	let a = Animals.troll
}

This is more useful in Error Handling.

The do-while loops has been renamed to repeat.

repeat {
	println("eyoo")
} while i < 5

Option Sets

You have seen them as or’s before.

viewAnimationOptions = .Repeat | .CurveEaseIn | .TransitionCurlUp

In Swift 2, they have a different syntax. In Swift 1.2, a First Class Set Type. Option Sets and Sets are now formed with this new syntax:

viewAnimationOptions = [.Repeat, .CurveEaseIn, .TransitionCurlUp]

This means you can use empty brackets to create an empty set, and checking if it contains a value is much nicer too:

if viewAnimationOptions.contains(.TransitionCurlUp) {
	
}

You can also define your own option sets in a much easier way: Define your own struct type, have it conform to the OptionSetType protocol, and define some storage to hold your tips, and the define the elements you want for your option set.

struct MyFontStyle : OptionSetType {
	let rawValue: Int
	static let Bold 		 = MyFontStyle(rawValue: 1)
	static let Italic  		 = MyFontStyle(rawValue: 2)
	static let Underline 	 = MyFontStyle(rawValue: 4)
	static let StrikeThrough = MyFontStyle(rawValue: 8)
}

myFont.style = []
myFont.style = [.Underline]
myFont.style = [.Bold, .Italic]

if myFont.style.contains(.StrikeThrough) {

}

(It is recommended to watch the Protocol-Oriented Programming in Swift session).

Functions and Methods

Swift 1 was following the steps of Objective-C:

– No label for global functions
– Labels for second argument (and later) in methods.

In Swift 2, functions and methods have the same declaration syntax, so when calling global functions, you provide labels by default. This doesn’t change in imported C and Objective-C APIs.

Argument Label Controls

The “_” syntax in method declaration to avoid specifying a different label name than internal parameter name.

func save(_ name: String, encrypt encrypt: Bool)

You can of course replace the underscore for a label name. The function definition above is what Swift uses by convention (first parameter doesn’t need a label, everything else does.

Swift 2 has a much simpler model for the whole argument label thing:

– Consistency between functions and methods.
– No special rules for defaulted parameters.
– The “#” syntax has been removed. In Swift 1, you used the # syntax to specify the label and parameter name at the same time. Therefore doing this is no longer possible in Swift 2:

func save(_ name: String, #encrypt: Bool)

Unit Testing

Tests can access the internal and public symbols when using the keyword “@testable”.

@testable
import MyApp

Rich Playgrounds

You can create much nicer documentation using Markdown. From font styles to images, almost everything can be included.

Swift Fundamentals not Covered:

– Default implementations in Protocols.
– C Function pointers + closures.
– Recursive nested functions.
– if/do labeled breaks.
– SIMD Vectors.
– Mirrors API.
– readLine().
– @nonobjc

Pattern Matching

First used in the “if let” statement. The problem is you can nest them to deep pyramids and it’s hard to understand. Swift 2 introduces Compound Conditions to avoid this:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
	if let dest = segue.destinationViewController as? BlogViewController
	   let blogIndex = tableView.indexPathForSelectedRow()?.row
	   where segue.identifier == blogSegueIdentifier {
	       dest.blogName = swiftBlogs[blogIndex]
	   }
}

You can check multiple optionals and even conditions.

Patterns for Early Exits

You can force-unwrap optionals early so you don’t find yourself doing that too often, specially if your code is too long. This won’t cause a crash.

func process(json: AnyObject) -> Either<Person, String> {
	let name: String! = json["name"] as? String
	if let name == nil {
		return .Second("missing name")
	}
	let year: Int! = json["year"] as? Int
	if year == nil {
		return .Second("missing year")
	}
	let person = processPerson(name, year)
	return .First(person)
}

But this is ugly too. To exit early, you can now use the “guard” statement.

guard let name = json["name"] as? String else {
	return .Second("missing name")
}

It guarantees else exits the current scope.

The code for process now looks much nicer:

func process(json: AnyObject) -> Either<Person, String> {
	guard let name = json["name"] as? String else {
		return .Second("missing name")
	}
	guard let year = json["year"] as? Int else {
		return .Second("missing name")
	}
	let person = processPerson(name, year)
	return .First(person)
}

This works nice with multiple conditions, so the code above can be made even nicer:

func process(json: AnyObject) -> Either<Person, String> {
	guard let name = json["name"] as? String, guard let year = json["year"] as? Int else {
		return .Second("bad input")
	}
	let person = processPerson(name, year)
	return .First(person)
}

Switches

They have always been the best thing of pattern matching. But they are heavy when you only want to check one condition. So the following:

switch bar() {
	case .MyEnumCase(let value) where value !+ 42:
	doThing(value)

	default: break
}

Can be better written this way in Swift 2:

if case .MyEnumCase(let value) = bar() where value != 42 {
	doThing(value)
}

for… in Filtering

Swift 2 gives you a very nice way to filter results in a for… in loop, and also allows you to use pattern matching in for … in loops:

for value in mySequence where value != "" {
	doThing(value)
}
for case .MyEnumCase(let value) in enumValues {
	doThing(value)
}

Other Improvements

– x? pattern for optionals.
– Improvement exhaustiveness checker.
– Unreachable case warning.

API Availability Checking

extension NSButton {
	@available(OSX 10.10.3)
	var springLoaded: Bool
}

You can check for versions like this:

override func awakeFromNib() {
	if #available(OSX 10.10.3, *) {
		dropButton.springLoaded = true
	}
}

You could also use the guard statement.

Protocol Extensions

You can extend protocols themselves. In the video, it is pointed that something you add to an array may apply to all collection types, so we are shown we can extend protocols themselves. For example this:

extension CollectionType {
	func countIf(match: Element -> Bool) -> Int {
		var n = 0
		for value in self {
			if match(value) { n++ }
		}
		return n
	}
}

Is added to everything that implements CollectionType.

Global generic algorithms are becoming methods.

Error Handling

The main purpose is to help get rid of the overflow of NSErrors everywhere.

There are two components to deal with Errors in Swift. First, the try keyboard is used before an API that can throw an error. Second, every method that throws something needs to have the throws keyboard after the parenthesis in the method name. Any code that is preceded by throw, must be inside a do, and that must be accompanied by a catch (which can be used pattern matching on). Using Pattern matching allows you to catch different kinds of errors.

func preflight() throws {

}
func preflight() -> Bool {
	do {
		try url.checkResourceIsReachable()
		resetState()
		return true
	} catch NSURLError.FileDoesNotExist {
		return true
	} catch let error {
		return false
	}
}

You can also use the fatalError() function for extreme scenarios. Used when you can’t recover from the error.

To mark something as Impossible Errors, follow the try keyword with a !. If your program throws an error in that situation, your program will crash.

func preflight() {
	try! url.checkResourceIsReachable()
	resetState()
}

You can throw anything whose type conforms to ErrorType.

Enums are great to conform to ErrorType.

enum DataError: ErrorType {
	
}

You can make your function do something at the end of execution. A defer statement creates an action that gets called when exciting the current scope. That means that instead of doing something like this:

func process(json: AnyObject) -> Either<Person, String> {
	delegate?.didBeginReadingSale()
	guard let name = json["name"] as? String else {
		delegate?.didEndReadingSale()
		throw DataError.MissingName
	}
	guard let year = json["year"] as? Int else {
		delegate?.didEndReadingSale
		return .Second("missing name")
	}
	let person = processPerson(name, year)
	delegate?.didEndReadingSale()
	return .First(person)
}

You can do this:

func process(json: AnyObject) -> Either<Person, String> {
	delegate?.didBeginReadingSale()
	defer{ delegate?.didEndReadingSale() }
	guard let name = json["name"] as? String else {
		throw DataError.MissingName
	}
	guard let year = json["year"] as? Int else {
		return .Second("missing name")
	}
	let person = processPerson(name, year)
	return .First(person)
}
Positive SSL