嵌套 do catch swift 3.0

Nested do catch swift 3.0

我想使用连续的 try 语句。如果一个 return 是一个错误,我想继续下一个,否则 return 值。 下面的代码似乎工作正常,但我最终会得到一个大的嵌套 do catch 金字塔。在 Swift 3.0 中有 smarter/better 的方法吗?

do {
    return try firstThing()
} catch {
    do {
        return try secondThing()
    } catch {
        return try thirdThing()
    }
}

如果不需要从那些函数调用中抛出的实际错误 然后你可以使用 try? 将结果转换为可选的, 并使用零合并运算符 ??.

链接调用

例如:

if let result = (try? firstThing()) ?? (try? secondThing()) ?? (try? thirdThing()) {
    return result
} else {
    // everything failed ...
}

或者,如果一切都失败了,最后一个方法的错误应该被抛出, 对除最后一个方法调用之外的所有方法使用 try?

return (try? firstThing()) ?? (try? secondThing()) ?? (try thirdThing())

如果 Martin 的回答对您来说过于简洁,您可以使用单独的 catch 块。

do {
    return try firstThing()
} catch {}

do {
    return try secondThing()
} catch {}

do {
    return try thirdThing()
} catch {}

return defaultThing()

由于每个抛出函数的结果都会立即返回,因此无需嵌套。

另一种方法是编写一个将所有抛出函数作为参数的函数。它returns第一个成功执行或为零。

func first<T>(_ values: (() throws -> T)...) -> T? {
    return values.lazy.flatMap({ (throwingFunc) -> T? in
        return try? throwingFunc()
    }).first
}

lazy 确保仅在找到第一个匹配项之前调用这些值。这样做,你也可以很快的添加很多案例。

你可以这样使用函数

return first(firstThing, secondThing, thirdThing) ?? "Default"

我还包括了我用来在操场上测试它的代码:

enum ThingError: Error {
    case zero
}

func firstThing() throws -> String {
    print("0")
    throw ThingError.zero
    return "0"
}

func secondThing() throws -> String {
    print("1")
    return "1"
}

func thirdThing() throws -> String {
    print("2")
    return "B"
}

func first<T>(_ values: (() throws -> T)...) -> T? {
    return values.lazy.flatMap({ (throwingFunc) -> T? in
        return try? throwingFunc()
    }).first
}

func tryThings() -> String {
    return first(firstThing, secondThing, thirdThing) ?? "Default"
}

tryThings() // prints "0" and "1"