Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catching a default error in Swift

I am trying to learn Swift, and wondered about Apple's expected answer to the experiment below which is provided in the Error Handling section of Apple's GuidedTour playground as follows;

Experiment: Add code to throw an error inside the do block. What kind of error do you need to throw so that the error is handled by the first catch block? What about the second and third blocks?

enum PrinterError: ErrorType {
    case OutOfPaper
    case NoToner
    case OnFire
}

func sendToPrinter(printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.NoToner
    }
    return "Job sent"
}

do {
    let printerResponse = try sendToPrinter("Gutenberg")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

Below are my answers to the questions asked in this experiment, and they all seem to work...

What kind of error do you need to throw so that the error is handled by the first catch block?

By adding throw PrinterError.OnFire as below;

do {
    throw PrinterError.OnFire
    let printerResponse = try sendToPrinter("Gutenberg")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

What about the second...

By sending "Never Has Toner" to sendToPrinter.

do {
    let printerResponse = try sendToPrinter("Never Has Toner")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

...and third blocks?

The only way I can trigger the third block -and the expected answer in my opinion in this case- is to create a different enum conforming to ErrorType and to throw it, as below;

enum anotherEnum: ErrorType {
    case someCase
}

do {
    throw anotherEnum.someCase
    let printerResponse = try sendToPrinter("Gutenberg")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

However, as the first sentence for this experiment starts with "Add code to throw an error inside the do block.", I wondered if there was another expected answer that I was supposed to find out while staying in the do block.

I'm asking because I don't want to miss something else that I was expected to find out. Do you think these answers are valid from Apple's perspective?

Thank you!

like image 883
emreerokyar Avatar asked May 26 '16 23:05

emreerokyar


People also ask

How do you catch errors in Swift?

There are four ways to handle errors in Swift. You can propagate the error from a function to the code that calls that function, handle the error using a do - catch statement, handle the error as an optional value, or assert that the error will not occur.

Do try catch Swift error?

The try/catch syntax was added in Swift 2.0 to make exception handling clearer and safer. It's made up of three parts: do starts a block of code that might fail, catch is where execution gets transferred if any errors occur, and any function calls that might fail need to be called using try .

What does default mean in Swift?

Swift provides a default initializer for any structure or class that provides default values for all of its properties and doesn't provide at least one initializer itself. The default initializer simply creates a new instance with all of its properties set to their default values.

What is Nserror in Swift?

Information about an error condition including a domain, a domain-specific error code, and application-specific information.


1 Answers

A more practical example of that third scenario might be something like checking to see if the network was available before even bothering to try sending something to the network printer:

enum NetworkError: ErrorType {
    case Unavailable
}

enum PrinterError: ErrorType {
    case OutOfPaper
    case NoToner
    case OnFire
}

func sendToPrinter(printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.NoToner
    }
    return "Job sent"
}

var networkAvailable = false     // some other process will update this when the network is available

Then you could do:

do {
    if !networkAvailable {
        throw NetworkError.Unavailable
    }

    let printerResponse = try sendToPrinter("Gutenberg")
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

This will result in the third catch block being caught.

Or a more realistic, Cocoa example might be:

do {
    let documents = try NSFileManager.defaultManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
    let fileURL = documents.URLByAppendingPathComponent("document.txt")
    let contents = try String(contentsOfURL: fileURL)

    let printerResponse = try sendToPrinter(contents)
    print(printerResponse)
} catch PrinterError.OnFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}

Note, this isn't actually manually throwing an error, but relying upon errors thrown by URLForDirectory and String(contentsOfURL:). But if the document.txt was not found in the Documents folder, String(contentsOfURL:) would throw an error which would be caught by your third catch block.

like image 184
Rob Avatar answered Sep 22 '22 11:09

Rob