The Swift language has taken the iOS/OSX community by storm. In a matter of only a year, Swift has managed to climb from nineteenth to fifteenth position in the list of the most popular programming languages. Apart from the major performance improvements, Swift 2.0 also added tons of new language features including error handling, protocol extensions, availability APIs, and much more. The new features enabled the developers to write safer code and be productive at the same time.

In this article, I'll take a glance into the new features of the Swift language. I'll cover the most important features of the new Swift language and explore the practical aspects of each. At the end of this article, you'll be equipped with the information you need to take advantage of the new cool features of the Swift programming language.

Error Handling

Error handling is the process of responding to and recovering from error conditions in your program. Swift 2.0 introduces new language features for handling exceptions. In order to better understand Swift 2.0 exception handling, you must take a step back and look at the history of exception handling in the Cocoa framework.

The earlier releases of Objective-C didn't even have native exception handling. Exception handling was performed by using the NS_DURING, NS_HANDLER, and NS_ENDHANDLER macros, like this:

NS_DURING
    [self callSomeMethodThatMightThrowException];
NS_HANDLER
NSLog(@"Exception has occured");
NS_ENDHANDLER

The NS_DURING macro marks the beginning of the block containing the code that might throw an exception. The NS_HANDLER macro handles the actual exception and NS_ENDHANDLER marks the end of the exception-handling block. The callSomeMethodThatMightThrowException is implemented in this bit of code.

-(void) callSomeMethodThatMightThrowException {

[NSException raise:@"Exception" format:@"Something bad happened"];

}

As you can imagine, the exception handling in Objective-C wasn't very intuitive and majority of the developers didn't bother to implement any kind of exception handling in their Cocoa applications. The complex nature of exception handling in the earlier releases of Objective-C also contributed to a mindset among Cocoa developers where exceptions were used to mark unrecoverable errors. A common theme was to kill the application instead of recovering from the errors, which might result in corrupted data. This is the main reason that you can still witness a lot of Cocoa applications that provide no exception handling at all.

Apple addressed this issue by adding native exception handling with OS X 10.3. Native exception handling in Objective-C allowed developers to use a modern approach in handling exceptions within their Objective-C code, as shown here:

    @try {
        [self callSomeMethodThatMightThrowException];
    }
    @catch(NSException *exception) {

    // handle the error

    }
    @finally {

        // clean up code
        // code that is executed whether the
        // exception is thrown or not
    }

The @try keyword marks the beginning of the block where an exception can occur. The @catch is where the exception is handled. You can have multiple catch blocks to refine the type of exception you're handling. The @finally block is triggered regardless of whether an exception has occurred or not. The @finally block is ideal for cleaning up resources or closing connections.

The @finally block is ideal for cleaning up resources or closing connections.

Despite the progress in handling exceptions in Objective-C using native exception handling, developers still associate exceptions with catastrophic events. The recoverable errors were represented by the NSError class that predates exception handling. The NSError pattern was also inherited by Swift 1.x, as shown in in the next snippet. The error instance is returned as part of the callback method. If the error isn't nil, take an appropriate action to notify the user; otherwise, continue with the normal execution of the application, like this:

let session = NSURLSession()

session.dataTaskWithURL(NSURL(string: "")!)
{ (data :NSData?, response:NSURLResponse?, error :NSError?)
-> Void in

   if error != nil {

       // do something with the error
    }

    print("sss")

}.resume()

Swift 2.0 introduces modern error-handling to the Swift language that allows you to write “safe code” (pointers to error-free code). In Swift, the errors are represented by values of types conforming to the ErrorType protocol, as shown in the next snippet:

enum DebitCardError : ErrorType {
    case IncorrectPin
    case InsufficientFunds
}

In Swift, the error-handling block is referred as a do-catch block. The do block wraps the try keyword and serves as a container to call the potentially risky code. Methods that can throw an exception must contain the keyword throws right before their return type parameter and must be called using the try keyword. The next snippet shows the implementation of the Swipe method that's capable of throwing an exception.

struct Card {
    var number :Int
    var pin :Int
}

func swipe(card :Card) throws  {

    do {
        try authenticate(card.pin)
    }
    catch DebitCardError.IncorrectPin {
        print("Incorrect Pin")
    }

    catch DebitCardError.InsufficientFunds {
        print("Insufficient Funds")
    }
}

In the Authenticate method, the pin number is hardcoded and an exception is thrown if the pin number doesn't match, as shown here:

func authenticate(pin :Int) throws {

    if pin != 1234 {
        throw DebitCardError.InsufficientFunds
    }
}

Finally, create an instance of the Card class and call the Swipe method using the try keyword.

var card = Card(number: 9090, pin: 5555)
try swipe(card)

The try keyword is required when calling the Swipe method because the Swipe method is decorated with the throws keyword, indicating that it can throw an exception. There are some scenarios where a method throws an exception but instead of catching the exception, the best solution is to crash the app. Under those circumstances, you call the method using the syntax shown here:

try! swipe(card)

If you're calling a third-party library that doesn't have support for error handling, you might want to call those methods with the try! syntax.

An acute observer might have noticed that there's no finally block in the Swift language. In other modern languages, including C# and Java, the finally block is an optional part of the try-catch handler that executes whether the exception is thrown or not. The finally block is an ideal location to clean up the resources including closing database connections etc.

Swift uses the new defer keyword to serve the same purpose as the finally keyword. One big difference between defer and finally is that the defer block is executed at the end of its calling scope. This next snippet shows the execution flow for the defer keyword.

func doStuff() throws {

    print("This is before defer is called")
    // called first

    defer {
        print("Defer is called")
        // called third
    }

    print("This is also before defer is called")
    // called second
    }

try doStuff()

As you can see, even though the defer block appears before the last print statement, it will be last to get executed. Defer is a perfect place to perform resource cleanups, close database connections etc.

The modern syntax of Swift exception handling allows you to write safer code for applications that potentially provide a much richer user experience to the users and also provide you with relevant information to improve your existing applications.

Guard

In addition to the modern error handling introduced in Swift 2.0, the Swift team also added a new language keyword guard. Using a guard keyword ensures that the conditions are met or else the execution won't continue. From afar, you might feel that the guard statement provides the same logic flow as a class' if-else conditional statement, but it's really quite different. The next snippet shows a very simple function that checks the username length and takes appropriate action based on the validity of the username string.

var userName :String?

func loginButtonTapped() {

    if userName!.characters.count > 0 {
        print("do something")
    } else {
        print("invalid username")
    }
}

The function in this next snippet can be implemented using the new guard keyword. The implementation is shown in the previous section.

func loginButtonTapped() {

    guard userName?.characters.count > 0 else {
        return
    }

}

The guard statement makes sure that the execution of the application only continues if the conditions are met. Another great use of the guard keyword is to make your code more readable and beautiful.

Swift is a leap forward when compared to the Objective-C language but it also has dark corners. One of the smelly code issues in the Swift language is the use of force unwrap for the optional keyword "!". Using the guard keyword, you can force unwrap the instance at the same time, as shown here:

guard let url = NSURL(string: "http://www.code-magazine.com") 
else {
    fatalError("Error creating URL with the supplied parameters!")
} 

Guard not only simplifies the flow of the application but also enhances the readiness of the code. No longer do you have to use the ugly "!" syntax to unwrap the optional instances.

Using the guard keyword, you can also unwrap multiple optional instances.

Protocol Extensions

Swift 2.0 protocols can be extended to provide a method and property implementations to the conforming types. This means that you can define method and property implementations for your protocols that can be used as default implementations for the conforming classes. A few snippets ago, you declared a ManagedObjectType protocol. The ManagedObjectType is used by NSManagedObject entity classes that provide sorting behaviors. The next snippet shows the implementations of the ManagedObjectType protocol.

public protocol ManagedObjectType {

    static var entityName :String { get }
    static var defaultSortDescriptors :[NSSortDescriptor] { get }
}

In Swift 2.0, you can extend the ManagedObjectType protocol to include a default implementation of the protocol properties, like this:

extension ManagedObjectType {

    public static var defaultSortDescriptors:[NSSortDescriptor] {
        return []
    }
}

This means that every class inheriting from the ManagedObjectType protocol will also benefit from the default implementation of the defaultSortDescriptors. The concreate class can also provide a custom implementation that overrides the extension method implementation, as shown here:

extension Customer : ManagedObjectType {

    public static var entityName :String {
        return "Customer"
    }

    public static var defaultSortDescriptor:[NSSortDescriptor] {
        return [NSSortDescriptor(key: "dateCreated", ascending: false)]
    }
}

Protocol extensions in Swift 2.0 bridge a big gap in protocol adaptation and provide a default implementation of protocol methods and properties that can be used in concrete implementations.

Availability

Apple constantly improves their existing APIs and frameworks by adding new features. One of the challenges developers faced was to make sure that they only invoked the new APIs on the devices that run compatible versions of the iOS framework. This was accomplished by first making sure that the APIs existed before calling them. This next snippet shows the implementation using the RespondsToSelector method to make sure that the registerUserNotificationSettings exists before you call it.

func application(application: UIApplication
, didFinishLaunchingWithOptions
launchOptions: [NSObject: AnyObject]?) -> Bool {
    if UIApplication.instancesRespondToSelector
    ("registerUserNotificationSettings:") {
        let types = UIUserNotificationType
        .Alert | UIUserNotificationType.Sound | UIUserNotificationType.Badge
    let settings = UIUserNotificationSettings(forTypes: types, categories: nil)

    application.registerUserNotificationSettings(settings)
}

return true
}

Apart from being unclear, the previous implementation doesn't give any indication as of which iOS version you're checking against. Swift 2.0 solves this problem by providing the available API, making things much simpler and clearer. Using the available API, you can write the previous code like this:

func registerNotifications() {

    let types = UIUserNotificationType
.Alert | UIUserNotificationType.Sound | UIUserNotificationType.Badge
    let settings = UIUserNotificationSettings
(forTypes: types, categories: nil)
application.registerUserNotificationSettings(settings)
}

if #available(iOS 8.0, *) {

    registerNotifications()
}

The asterisk (in the “if #available” line) is required and indicates that the conditional check executes on the minimum deployment target for any platform that isn't included in the list of platforms. Of course, the available API isn't only limited to the iOS platform but can easily be extended to WatchOS, OSX, and tvOS as shown in this next snippet.

if #available(iOS 8.0, OSX 10.10, watchOS 2, *)
{

    // do something
}

You can even decorate your methods with the @available attribute, which ensures that the methods are only called on the selected platforms as shown here:

@available(iOS 8.0, *)
func someMethod() {

}

The available API provides an easy way to manage platform dependency in code, removing the cumbersome and illusive calls to the respondsToSelector method and provides a much cleaner and simpler implementation.

Objective-C Interoperability

The Swift language is fully interoperable with the Objective-C language, meaning that Swift can easily take advantage of the rich libraries implemented in the Objective-C language. This is great news because you can easily reuse your existing Objective-C code in your new Swift applications.

In addition to compatibility with Objective-C, Xcode 7 also includes a Swift migration tool that can be used to migrate Swift 1.0 code to Swift 2.0. The migration tool allows you to preview the new changes that include exception handling, guard, repeat, and verifying the availability of APIs before committing them.

Open Source

During a WWDC 2015 announcement, Apple announced that Swift will become open source. This is great news as we're brought one step closer to providing updates to the Swift language, provided that the Swift team is open to pulling changes from developers.

Conclusion

Swift 2.0 is a huge improvement from its predecessor Swift 1.0. Swift 2.0 provides improved performance, fast compilation, error handling, availability APIs, and protocol extensions, making it a more powerful and modern high-level language. With the release of Swift 2.0, things also seems to be calming down, which means that your existing code won't break as often with the new versions of the Swift language. As always, this is a great time to be an iOS developer and even a better time to be an iOS Swift developer.