当我们在一个方法或函数中实现某些功能时,如果遇到错误的用户输入则可能导致严重的异常问题,此时我们可以选择通过抛出异常的方式。Swift 团队在 Swift 2 中包含了一种很好的方式来处理与理想情况的偏差。Swift Error Handling 能够让我们快速而简便的告知编译器一个函数能否抛出错误,并且在抛出后以合适的方式去处理错误
主动退出程序的几种情况
在程序运行到相关代码的时候,会直接退出程序
- 1、Fatal Errors(致命的错误)
- 2、Assertions(断言)
- 3、先决条件(Preconditions)
1、Fatal Errors(致命的错误)
使用fatalError()函数可以立即终止你的应用程序,在fatalError()中可以给出终止信息。使用fatalError()函数,会毫无条件的终止你的应用程序,用起来也是比较简单的,就是一个函数的调用
fatalError("我是fatalError错误")
fatalError.png
2、Assertions(断言)
在单元测试中是少不了断言的,Swift中的断言和Objective-C的区别不是太大,使用方法也是大同小异。断言会在Debug模式下起作用,但是在Release版本中就会被忽略。
Assertions.png在assert()函数中, 第一个参数是Bool类型,第二个参数是输出的信息。当条件为true时,断言不执行,相应的断言信息不打印。当条件为false时,断言执行,并且打印相应的断言信息。
assert(true, "我是true断言")
assert(false, "我是false断言")
assert.png
3、先决条件(Preconditions)
Preconditions的用法和断言一样,Preconditions在debug和release模式下都会被执行,除非使用–Ounchecked进行编译
Preconditions.pngprecondition(true, "我是先决条件true")
precondition(false, "我是先决条件false")
Swift中的错误处理
1、使用枚举添加错误原因
定义错误类型
在 swift 中如果我们要定义一个表示错误的类型非常简单,只要遵循 Error 协议就可以了,我们通常用枚举或结构体来表示错误类型,枚举可能用的多些,因为它能更直观的表达当前错误类型的每种错误细节。
/// 定义一个枚举类型的错误类型
enum MyEnumError: Error {
case ErrorReasonOne
case ErrorReasonTwo
case ErrorReasonThree
}
错误类型抛出
在我们的函数定义时可以使用throws关键字,以及在函数中使用throw关键字对错误进行抛出,抛出的错误类型就可以使用上面我们自己定义的错误类型
func testThrow(a:Int) throws {
if a == 1 {
throw MyEnumError.ErrorReasonOne
}else if a == 2{
throw MyEnumError.ErrorReasonTwo
}else if a == 3{
throw MyEnumError.ErrorReasonThree
}
print("正常流程")
}
错误捕获与处理
上面函数的功能是对错误进行抛出,接下来就该使用do-catch来处理抛出的错误。使用try对错误进行捕捉,使用do-catch对错误进行处理。我们在catch的时候需要把每一种情况都列举出来。
do {
try testThrow(a: 1)
} catch MyEnumError.ErrorReasonOne {
print("错误理由:ErrorReasonOne")
}catch MyEnumError.ErrorReasonTwo {
print("错误理由:ErrorReasonTwo")
}catch MyEnumError.ErrorReasonThree {
print("错误理由:ErrorReasonThree")
}catch{
print("其他错误")
}
打印结果
错误理由:ErrorReasonOne
注意
只有抛出函数才能传递错误。任何在非抛出函数中抛出错误都必须在函数内部进行处理。
在枚举实现错误类型中我们可以通过值绑定的形式为错误添加错误代码和错误原因。
/// 定义一个枚举类型的错误类型
enum MyEnumError: Error {
case ErrorState(errorCode:Int,errorMessage:String)
}
override func viewDidLoad() {
super.viewDidLoad()
do {
try testThrow(a: 1)
} catch MyEnumError.ErrorState(let code,let message) {
print("错误码:\(code) 错误原因:\(message)")
}catch{
print("其他错误")
}
}
func testThrow(a:Int) throws {
if a == 1 {
throw MyEnumError.ErrorState(errorCode: 404, errorMessage: "找不到服务器")
}
print("正常流程")
}
打印结果
错误码:404 错误原因:找不到服务器
2、使用结构体为错误处理添加Reason
struct MyEnumError: Error {
let reason : String
}
override func viewDidLoad() {
super.viewDidLoad()
do {
try testThrow(a: 1)
} catch {
print(error)
}
}
func testThrow(a:Int) throws {
if a == 1 {
throw MyEnumError.init(reason: "404 找不到服务器")
}
print("正常流程")
}
最后要对抛出的错误进行do-catch处理,在处理时,可以对错误原因进行打印,错误原因存储在error中,具体操作和打印结果如下所示:
MyEnumError(reason: "404 找不到服务器")
3、使String类型遵循ErrorType协议,直接使用String提供错误原因
extension String:Error{}
override func viewDidLoad() {
super.viewDidLoad()
do {
try testThrow(a: 1)
} catch {
print(error)
}
}
func testThrow(a:Int) throws {
if a == 1 {
throw "404 找不到服务器"
}
print("正常流程")
}
4、try! try?
enum MyEnumError: Error {
case ErrorState(errorCode:Int,errorMessage:String)
}
func divide(_ a:Int,_ b:Int) throws -> Int {
if b == 0 {
throw MyEnumError.ErrorState(errorCode: 100, errorMessage: "除数不能为0")
}
return a / b
}
let result1 = try? divide(10, 1)
let result2 = try? divide(10, 0)
print(result1,result2)
let result3 = try! divide(10, 2)
let result4 = try! divide(10, 0)
print(result3,result4)
打印结果
try5、defer
defer
语句:用来定义以任何方式(抛错误,return等)离开代码前必须执行的代码,defer
语句将延迟至当前作用域之前执行
func test(){
defer {
print("打印defer")
}
do {
let _ = try divide(10, 0)
} catch let error {
print(error)
}
}
test()
550056DC-51C8-4786-828C-F8DEEC9DB622.png
参考
网友评论