Nayan
Nayan

Reputation: 3014

Swift 2.0 exception handling

We want to know error handling mechanism in SWIFT for whole block of code.

As, in swift, there are some techniques used for error handling, some of them are like using guard or if let. Also we can achieve it using do - catch statement. But we are getting stuck while handling error for whole bunch of code using single try-catch block as we were doing in Objective-C. In Objective-C this block was easily handling errors within any line of code in it. So we want to know this type of mechanism in swift.

For now, we came to know that if we need to handle error, then use guard, if-let statement for each line, or write some custom methods which will throw the error and use that method in do-catch block. So is there any mechanism in Swift which will be parallel to try-catch block just like in Objective-C so we don’t need to write if-let or guard statement for each single line of code in that whole bunch of code.

This is how we used if-let and guard let for single line statement null handling :

if-let implementation sample code snippet :-

if let title = dict["title"].string
{
   let myTitle = title
}

But below is mentioned scenario in which we want solution in swift for try-catch block within delegate functions.

A sample code snippet in Objective-C using try-catch block

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

    @try {
        static NSString *itemIdentifier = @"CustomCell";
        //Some line of code where exception may occur…
        //Some line of code where exception may occur…
        //Some line of code where exception may occur…
        //Some line of code where exception may occur…
        //…
        //…
        //… 
        return cell;
    }
    @catch (NSException *exception) {
        NSLog(@"Exception in  cellForItemAtIndexPath - %@“,exception.description);
    }
}

Above is the code snippet which we were using in Objective-C. But now we want to use same thing of try-catch in Swift. But till now we haven’t found any solution. So how do we handle such scenario in which we can add the try-catch block to delegate functions of table view, collection view, ... , etc.

Upvotes: 1

Views: 474

Answers (2)

ysholqamy
ysholqamy

Reputation: 221

As @JeremyP said, in swift there is no exceptions. To make this clear you can you can use a single do-catch block to catch multiple errors, nevertheless if-let and guard has to be used to avoid fatal errors which are not catchable. For example:

do {
  try method1()
  try method2()
} catch {
  // do something with the error 
}

but the previous example won't handle a fatal error, for example:

do {
  try method1()
  let myVar = anOptionalVar!
} catch {

}

this code won't handle a fatal error, if anOptionalVar is nil and you force unwrap it this will cause a fatal error which will terminate execution.

So the pattern described by @JeremyP should be used to handle errors:

enum myError: ErrorType {
  case BadError
}

do {
  guard let myVar = anOptionalVar else { throw MyError.BadError }
} catch MyError.BadError {
  // do something with the error
}

So as of swift 2 there is no way around using guard and if-let to stay safe from fatal errors, your only option is using them and propagate an ErrorType instead.

Upvotes: 1

JeremyP
JeremyP

Reputation: 86691

In Swift, there are no exceptions. In Objective-C, there are exceptions but you shouldn't really use them except for program terminating issues. The reason for this is that if a method calls other methods that throw exceptions and it doesn't handle the exception itself, it will almost certainly leak resources (memory, file descriptors etc).

In Swift, you can throw an error, but this is conceptually syntactic sugar for the NSError** pattern. You can throw anything that conforms to the ErrorType protocol but I think you can only add that on enums. Having said that, NSError conforms to ErrorType so you can throw an NSError.

You can declare a function that throws an error like this

enum MyError: ErrorType // Protocol for all errors that can be thrown
{
    case ReallyBad
    case NotSoBad
}

func aFuncThatThrows(foo: Int) throws -> Int
{
    guard foo >= 0 else { throw MyError.NotSoBad }
    // Other stuff
}

When you use such a function, you must mark it with a try so that the caller knows that an error can be thrown.

let bar = try aFuncThatThrows(-1)

The function you are in either has to rethrow the error by being declared with the throws keyword or it has to handle the error which it does with the do { ... } catch construction.

do
{
    let bar = try aFuncThatThrows(-1)
}
catch
{
    // handle errors
}

You can have multiple catch blocks that handle different kinds of errors if you want. e.g.

catch MyError.ReallBad
{
    // Handle really bad errors
}
catch MyError.NotSoBad
{
    // handle not so bad errors 
}
catch
{
    // Handle anything else - catches must be exhaustive. 
}

Upvotes: 1

Related Questions