捕获多个errorTypes?

时间:2016-04-19 21:35:27

标签: swift error-handling switch-statement

我正在寻找一种方法来捕捉catch中的多种类型的错误。我尝试了fallthrough和逗号分隔的样式与switch语句,但都不起作用。 docs对删除多个pattern 1没有任何说法。我不清楚哪种模式语法可以在这里工作。

错误定义(示例):

enum AppErrors {
  case NotFound(objectType: String, id: Int)
  case AlreadyUsed
}

使用:

do {
  //...
} catch AppErrors.NotFound {
  makeNewOne()
} catch AppErrors.AlreadyUsed {
  makeNewOne()
} catch {
  print("Unhandled error: \(error)")
}

不编译,是否可以做这样的事情?

do {
  //...
} catch AppErrors.NotFound, AppErrors.AlreadyUsed {
  makeNewOne()
} catch {
  print("Unhandled error: \(error)")
}

2 个答案:

答案 0 :(得分:10)

如果要捕获所有AppErrors,可以使用此模式:

catch is AppErrors

如果你正在寻找更具体的匹配,它似乎很快变得难看。

这将让我们抓住AppErrors的具体案例:

catch let error as AppErrors where error == .NotFound || error == .AlreadyUsed

这种语法似乎也有效:

catch let error as AppErrors where [.NotFound, .AlreadyUsed].contains(error)

为了完整起见,我还将添加此选项,它允许我们捕获两种不同类型的错误,但它不允许我们指定这些类型中的哪种情况:

catch let error where error is AppErrors || error is NSError

最后,基于我们捕获的任何符合ErrorType协议的事实,我们可以清理第二个&第三个示例我提供了一个ErrorType扩展名,并将where中的catch子句与extension ErrorType { var isFooError: Bool { guard let err = self as? AppErrors else { return false } return err == .NotFound || err == .AlreadyUsed } } 一起使用:

catch let error where error.isFooError

就这样抓住它:

{{1}}

答案 1 :(得分:1)

您可以创建包含AppErrors数组的案例:

indirect enum AppErrors: Error {
  case NotFound
  case AlreadyUsed
  case errors([AppErrors])
}

然后,对于catch语句:

catch AppErrors.errors(let errors) where errors == [.NotFound, .AlreadyUsed]

请注意,与errors比较时,Array==顺序。另一种方法是使用case errors(Set<AppErrors>),但这需要AppErrors符合Hashable协议。

更新:想想看,最好使用OptionSet类型:

public struct InvalidInput: OptionSet, Error {
    public var rawValue: Int

    public init(rawValue: Int) {
        self.rawValue = rawValue
    }

    public static let noAccount  = InvalidInput(rawValue: 1 << 0)
    public static let noKey      = InvalidInput(rawValue: 1 << 1)
    public static let invalidKey = InvalidInput(rawValue: 1 << 2)
}

func validateInput() throws -> Void {
    var invalid: InvalidInput = []

    invalid.insert(.noKey)
    invalid.insert(.noAccount)

    if !invalid.isEmpty {
        throw invalid
    }
}

do {
    try validateInput()
} catch [InvalidInput.noAccount, InvalidInput.noKey] as InvalidInput {
    print("Account and key are both required.")
}

链接:http://www.chrisamanse.xyz/2016/12/03/catching-multiple-errors-in-swift