【问题标题】:Catching a default error in Swift在 Swift 中捕获默认错误
【发布时间】:2016-09-25 03:23:41
【问题描述】:

我正在尝试学习 Swift,并想知道 Apple 对以下实验的预期答案,该答案在 Apple 的 GuidedTour 操场的 错误处理 部分中提供,如下所示;

实验:添加代码以在 do 块内引发错误。您需要抛出什么样的错误,以便第一个 catch 块处理该错误?第二块和第三块呢?

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

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

你需要抛出什么样的错误,以便第一个catch块处理错误?

如下添加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)
}

第二个呢……

通过向 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)
}

...还有第三个区块?

我可以触发第三个块的唯一方法 - 在这种情况下我认为预期的答案 - 是创建一个不同的 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 区 中发现这一点。

我之所以这么问,是因为我不想错过其他我应该知道的事情。从 Apple 的角度来看,您认为这些答案是否有效?

谢谢!

【问题讨论】:

  • 说得对,很好:-)。我的意思是写“错误”而不是“异常”,马上更正。
  • 我刚刚再次检查,它就在那里。打开操场后,代码末尾有一个“下一步”按钮。我可以通过单击“下一步”6 次导航到“错误处理”部分。
  • 您的第三个示例很好地说明了如何被第三个 catch 块捕获,尽管您可能希望坚持标准命名约定,例如enum AnotherErrorType: ErrorType { case SomeOtherError }。或者你可以抛出一个NSError。显然,你很少有一个do-catch 块,其第一行是throw,但如果满足某些条件,你通常只会throw(例如,你可能有一些方法检查查看打印机是否在线,如果离线,则抛出其他错误)。但看起来你已经掌握了基本概念。
  • @Rob,非常感谢您检查此代码并发现我在标题中犯的错误,我很感激 :-)。我只是试图以最快的方式执行 Apple 期望其学习者完成的事情,所以是的,放在第一行似乎很尴尬,但对于这个例子来说,我认为它完成了工作。跨度>
  • 哇,很高兴知道苹果内部有一些IT Crowd fans :)

标签: ios swift exception try-catch throw


【解决方案1】:

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

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 块捕获。

【讨论】:

    猜你喜欢
    • 2016-03-08
    • 2017-03-19
    • 1970-01-01
    • 2015-10-06
    • 2015-09-14
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多