我试着去理解swift 2中新的错误处理。下面是我所做的:我首先声明了一个错误枚举:
enum SandwichError: ErrorType {
case NotMe
case DoItYourself
}
然后我声明了一个抛出错误的方法(不是异常,伙计们。它是一个错误)。下面是这个方法:
func makeMeSandwich(names: [String: String]) throws -> String {
guard let sandwich = names["sandwich"] else {
throw SandwichError.NotMe
}
return sandwich
}
问题来自调用方。下面是调用此方法的代码:
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
行之后,编译器说Errors thrown from here are not handled because the enclosing catch is not exhaustive
。但在我看来,它是详尽的,因为在SandwichError
枚举中只有两种情况。
对于常规的switch语句,swift可以理解它在处理每种情况时都是详尽的。
7条答案
按热度按时间34gzjxbg1#
Swift 2错误处理模型有两个要点:它们合在一起,可以归结为您的
do
/catch
语句需要捕获每个可能的错误,而不仅仅是那些您知道会抛出的错误。注意,我们没有声明函数会抛出什么类型的错误,只声明它是否会抛出错误,这是一个0 - 1-无穷大类的问题:作为一个定义函数供他人(包括未来的自己)使用的人,您不希望函数的每个客户端都必须适应函数实现中的每一个变化,包括它可能引发的错误。您希望调用函数的代码能够适应这种变化。
因为你的函数不能说明它抛出的错误类型(或者将来可能会抛出),捕获错误的
catch
块不知道它可能抛出什么类型的错误。您需要使用通用的catch
语句来处理那些不需要的错误--这样,如果您的函数更改了它在将来抛出的错误集,调用方仍将捕获它的错误。但是,我们不能就此止步,我们还要再思考一下这种弹性的概念。在设计三明治时,你必须描述每一个使用错误的地方。这意味着,每当你改变错误案例集时,你就必须改变每一个使用它们的地方......这可不是什么好玩的事。
定义您自己的错误类型的想法是让您集中处理类似的事情。您可以为您的错误定义一个
description
方法:然后,错误处理代码可以要求错误类型描述其自身--现在,处理错误的每个地方都可以使用相同的代码,并且还可以处理将来可能出现的错误情况。
这也为错误类型(或它们的扩展)支持其他报告错误的方式铺平了道路--例如,您可以在错误类型上有一个扩展,它知道如何向iOS用户提供一个
UIAlertController
来报告错误。r1zk6ea12#
我怀疑这只是还没有得到正确的实现。Swift编程指南似乎明确暗示编译器可以推断出穷举匹配'就像switch语句'。它没有提到需要一个通用的
catch
才能做到穷举。您还将注意到,错误出现在
try
行,而不是块的末尾,也就是说,在某个点上,编译器将能够查明块中的哪个try
语句具有未处理的异常类型。虽然文档有点模糊,我浏览了一下“Swift的新功能”视频,没有找到任何线索;我会继续努力的
更新日期:
我们现在到了Beta 3,没有任何ErrorType推断的提示。我现在相信,如果这是曾经计划过的(我仍然认为在某个时候是计划过的),协议扩展上的动态调度可能会杀死它。
测试版4更新:
Xcode 7 b4增加了对
Throws:
的doc注解支持,这“应该用来记录可以抛出什么错误以及为什么”,我猜这至少提供了 * 一些 * 机制来将错误传达给API消费者,当你有文档的时候,谁还需要类型系统呢!其他更新:
在花了一些时间希望自动
ErrorType
推理,并找出该模型的局限性后,我改变了主意--我希望苹果实现的是this。本质上:另一项更新
Apple的错误处理基本原理现在可以在here上找到。在swift-evolution邮件列表上也有一些有趣的讨论。本质上,John McCall反对类型化错误,因为他相信大多数库最终都会包含一个通用的错误情况。并且类型化的错误不太可能在代码中添加太多内容克里斯·拉特纳(Chris Lattner)说,如果Swift 3能与弹性模型一起工作,他愿意接受Swift 3中的输入错误。
k97glaaz3#
Swift担心case语句没有覆盖所有case,要解决这个问题,需要创建一个默认case:
uplii1fm4#
我也对缺少一个函数可以抛出的类型感到失望,但是我现在得到了它,这要感谢@rickster,我将这样总结它:假设我们可以指定一个函数抛出的类型,我们会得到如下结果:
问题是,即使我们不更改myFunctionThathrows中的任何内容,如果我们只是向MyError添加一个错误用例:
我们就完蛋了,因为我们的do/try/catch不再是详尽无遗的,我们调用抛出MyError的函数的任何其他地方也是如此
u3r8eeie5#
现在验证编号:
x8goxv8g6#
可以使用catch中的switch case来处理错误
mum43rcc7#
创建如下枚举:
创建方法如下:
现在检查有无错误并处理: