Swift do-try-catch 语法 [英] Swift do-try-catch syntax

查看:27
本文介绍了Swift do-try-catch 语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试理解 swift 2 中新的错误处理内容.这是我所做的:我首先声明了一个错误枚举:

I give it a try to understand new error handling thing in swift 2. Here is what I did: I first declared an error enum:

enum SandwichError: ErrorType {
    case NotMe
    case DoItYourself
}

然后我声明了一个抛出错误的方法(不是异常,这是一个错误.).方法如下:

And then I declared a method that throws an error (not an exception folks. It is an error.). Here is that method:

func makeMeSandwich(names: [String: String]) throws -> String {
    guard let sandwich = names["sandwich"] else {
        throw SandwichError.NotMe
    }

    return sandwich
}

问题出在调用方.下面是调用这个方法的代码:

The problem is from the calling side. Here is the code that calls this method:

let kitchen = ["sandwich": "ready", "breakfeast": "not ready"]

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it (sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
}

do 行之后,编译器说从这里抛出的错误没有被处理,因为封闭的catch 不是详尽的.但在我看来,它是详尽无遗的,因为 SandwichError 枚举中只有两种情况.

After the do line compiler says Errors thrown from here are not handled because the enclosing catch is not exhaustive. But in my opinion it is exhaustive because there is only two case in SandwichError enum.

对于常规的 switch 语句,swift 可以理解它在处理每个案例时都是详尽无遗的.

For regular switch statements swift can understands it is exhaustive when every case handled.

推荐答案

Swift 2 错误处理模型有两个重点:详尽性和弹性.它们一起归结为您的 do/catch 语句,需要捕获所有可能的错误,而不仅仅是您知道可以抛出的错误.

There are two important points to the Swift 2 error handling model: exhaustiveness and resiliency. Together, they boil down to your do/catch statement needing to catch every possible error, not just the ones you know you can throw.

请注意,您没有声明函数可以抛出什么类型的错误,只声明它是否会抛出.这是一个零一无穷大的问题:当有人定义一个函数供他人(包括你未来的自己)使用时,你不希望你的函数的每个客户端都适应你的函数实现中的每一个变化.函数,包括它可能抛出的错误.您希望调用您的函数的代码能够适应这种变化.

Notice that you don't declare what types of errors a function can throw, only whether it throws at all. It's a zero-one-infinity sort of problem: as someone defining a function for others (including your future self) to use, you don't want to have to make every client of your function adapt to every change in the implementation of your function, including what errors it can throw. You want code that calls your function to be resilient to such change.

因为你的函数不能说出它抛出什么类型的错误(或者将来可能抛出),捕获它错误的 catch 块不知道它可能抛出什么类型的错误.因此,除了处理您所知道的错误类型之外,您还需要使用通用的 catch 语句来处理您不知道的错误类型——如果您的函数更改了它抛出的错误集,则可以这样处理未来,调用者仍然会发现它的错误.

Because your function can't say what kind of errors it throws (or might throw in the future), the catch blocks that catch it errors don't know what types of errors it might throw. So, in addition to handling the error types you know about, you need to handle the ones you don't with a universal catch statement -- that way if your function changes the set of errors it throws in the future, callers will still catch its errors.

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it (sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
} catch let error {
    print(error.localizedDescription)
}

但我们不要就此止步.再想想这个弹性的想法.根据您设计三明治的方式,您必须在使用它们的每个地方描述错误.这意味着无论何时更改错误案例集,您都必须更改使用它们的每个地方......不是很有趣.

But let's not stop there. Think about this resilience idea some more. The way you've designed your sandwich, you have to describe errors in every place where you use them. That means that whenever you change the set of error cases, you have to change every place that uses them... not very fun.

定义您自己的错误类型背后的想法是让您集中处理类似的事情.你可以定义一个 description 错误的方法:

The idea behind defining your own error types is to let you centralize things like that. You could define a description method for your errors:

extension SandwichError: CustomStringConvertible {
    var description: String {
        switch self {
            case NotMe: return "Not me error"
            case DoItYourself: return "Try sudo"
        }
    }
}

然后你的错误处理代码可以要求你的错误类型描述它自己——现在你处理错误的每个地方都可以使用相同的代码,并且也可以处理未来可能的错误情况.

And then your error handling code can ask your error type to describe itself -- now every place where you handle errors can use the same code, and handle possible future error cases, too.

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it (sandwich)")
} catch let error as SandwichError {
    print(error.description)
} catch {
    print("i dunno")
}

这也为错误类型(或它们的扩展)铺平了道路,以支持其他报告错误的方式——例如,你可以在你的错误类型上有一个扩展,它知道如何呈现一个 UIAlertController 用于向 iOS 用户报告错误.

This also paves the way for error types (or extensions on them) to support other ways of reporting errors -- for example, you could have an extension on your error type that knows how to present a UIAlertController for reporting the error to an iOS user.

这篇关于Swift do-try-catch 语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆