ios – 在Swift中捕获默认错误

我正在尝试学习
Swift,并想知道苹果公司对苹果公司
GuidedTour游乐场的错误处理部分提供的实验的预期答案如下;

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)
}

以下是我对这个实验中提出的问题的回答,它们似乎都有效……

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

通过添加throw PrinterError.OnFire,如下所示;

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…

通过sendToPrinter发送“Never Has Toner”.

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?

在这种情况下,我可以触发第三个块的唯一方法 – 以及我认为的预期答案 – 是创建一个符合ErrorType的不同枚举并抛出它,如下所示;

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)
}

但是,正如本实验的第一句开头是“添加代码以在do块中抛出错误.”,我想知道是否还有另一个预期的答案,我应该在停留在do块时找到答案.

我问,因为我不想错过我期望找到的其他东西.从Apple的角度来看,您认为这些答案是否有效?

谢谢!

最佳答案 第三种情况的一个更实际的例子可能是在尝试向网络打印机发送内容之前检查网络是否可用:

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

然后你可以这样做:

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)
}

这将导致第三个捕获块被捕获.

或者更现实的Cocoa示例可能是:

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)
}

注意,这实际上并不是手动抛出错误,而是依赖于URLForDirectory和String(contentsOfURL :)抛出的错误.但是如果在Documents文件夹中找不到document.txt,则String(contentsOfURL :)会抛出一个错误,该错误将被第三个catch块捕获.

点赞