在 Swift 中捕获默认错误

Catching a default error in Swift

我正在努力学习 Swift,并且想知道 Apple 对以下实验的预期答案,该答案在 Apple 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...

通过发送"Never Has Toner"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?

我可以触发第三个块的唯一方法 - 以及我认为在这种情况下的预期答案 - 是创建一个不同的 enum 符合 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 block.

期间是否还有另一个我应该找到的预期答案

我问这个问题是因为我不想错过其他我应该知道的事情。您认为从 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)
}

这将导致第三个 catch 块被捕获。

或者更现实的 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)
}

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