Error-Handling in Swift-Language

I haven't read too much into Swift but one thing that i noticed is there are no exceptions. So how do they do error handling in swift? Has anyone found anything to error-handling?

Answers


Runtime errors:

As Leandros suggests for handling runtime errors (like network connectivity problems, parsing data, opening file, etc) you should use NSError like you did in ObjC, because the Foundation, AppKit, UIKit, etc report their errors in this way. So it's more framework thing than language thing.

Another frequent pattern that is being used are separator success/failure blocks like in AFNetworking:

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

Still the failure block frequently received NSError instance, describing the error.

Programmer errors:

For programmer errors (like out of bounds access of array element, invalid arguments passed to a function call, etc) you used exceptions in ObjC. Swift language does not seem to have any language support for exceptions (like throw, catch, etc keyword). However, as documentation suggests it is running on the same runtime as ObjC, and therefore you are still able to throw NSExceptions like this:

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

You just cannot catch them in pure Swift, although you may opt for catching exceptions in ObjC code.

The questions is whether you should throw exceptions for programmer errors, or rather use assertions as Apple suggests in the language guide.

Swift 2.0 update

Things have changed a bit in Swift 2.0, as there is a new error-handling mechanism, that is somewhat more similar to exceptions but different in detail.

  1. Indicating error possibility

If function/method wants to indicate that it may throw an error, it should contain throws keyword like this

func rideTheDragon() throws { ... }

Note: there is no specification of what function actually can throw, it is either throwing any error or not throwing anything at all.

  1. Invoking function that may throw errors

In order to invoke function you need to use try keyword, like this

try rideTheDragon(dragon: Dragon)

this line should normally be present do-catch block like this

do {
    try rideTheDragon(redDragon) 
} catch DragonError.DragonIsMissing {
    // Error-handling
} catch DragonError.NotEnoughMana(let manaRequired) {
    // More error-handlng
} catch {
    // Catch all error-handling
}

Note: catch clause use all the powerful features of Swift pattern matching so you are very flexible here.

Alternatively in function that is itself marked with throws keyword like this

func fullFillQuest(quest: Quest) throws {
    try rideTheDragon(quest.dragon)
} 

Last but not least, you can decide that you know that error will not actually occur, e.g. because you have already checked are prerequisites, and use try! keyword.

try! rideTheDragon(goldenDragon)

If the function actually throws the error, then you'll get a runtime error in your application.

  1. Throwing an error

In order to throw an error you use throw keyword like this

throw DragonError.DragonIsMissing

You can throw anything that conforms to ErrorType protocol. For starters NSError conforms to this protocol but you probably would like to go with enum-based ErrorType which enables you to group multiple related errors, potentially with additional pieces of data, like this

enum DragonError: ErrorType {
    case DragonIsMissing
    case NotEnoughMana(manaRequired: Int)
    ...
}

Main differences between new Swift 2.0 error mechanism and Java/C#/C++ style exceptions are follows:

  • Syntax is a bit different: do-catch + try + defer vs traditional try-catch-finally syntax.
  • Exception handling usually incurs much higher execution time in exception path than in success path. This is not the case with Swift 2.0 errors, where success path and error path cost roughly the same.
  • All error throwing code must be declared, while exceptions might have been thrown from anywhere. All errors are "checked exceptions" in Java nomenclature. However, in contrast to Java, you do not specify potentially thrown errors.
  • Swift exceptions are not compatible with ObjC exceptions. Your do-catch block will not catch any NSException, and vice versa, for that you must use ObjC.
  • Swift exceptions are compatible with Cocoa NSError method conventions of returning either false (for Bool returning functions) or nil (for AnyObject returning functions) and passing NSErrorPointer with error details.

As an extra syntatic-sugar to ease error handling, there are two more concepts

  • deferred actions (using defer keyword) which let you achieve the same effect as finally blocks in Java/C#/etc
  • guard statement (using guard keyword) which let you write little less if/else code than in normal error checking/signaling code.

Need Your Help

MySQL Select: find records with related records of only one type

php mysql

I'm pretty new to MySQL (coming from FileMaker) and struggle with this. I have to create a list from a MySQL database that meets this definition: List all records from table Children that do not ha...

MVC 5 With Tinymce Editor Contain Words “FIND”, “SERVICES” and some more around 8 more letter “ERR_CONNECTION_RESET”

post model-view-controller replace find tinymce

recently i am facing problem on my all MVC applications using TinyMce editor i am using that editor to allow users to input content of the page, strange things is happening now. when ever they have...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.