swift 是一个类型严格的语言,在很多情况下各种不匹配或者强制解包出错都会导致系统崩溃。所以我们需要进行异常处理,在swift中也叫错误处理Error。
Swift中可以通过Error协议自定义运行时的错误信息。在开发中常常也和枚举enum一起使用。Error协议其实是个空协议。比如这样定义error枚举
enum MyError: Error {
case error1((Int,String))
case error2((Int,String))
case error3((Int,String))
}
对于有可能崩溃的代码,在swift中可以通过throws关键来抛出错,给调用方去处理异常。如果没人处理,最终会导致App崩溃闪退。
对于有throws关键字的函数,调用的时候要加try关键字。
// 通过关键字throws来抛出错误。
// 这个函数num2为0的时候会崩溃的,除数不能为0
func divNum(_ num1: Int, _ num2: Int) throws -> Int {
let result = num1 / num2
return result
}
// 对于有throws关键字的函数,调用的时候要加try
try divNum(10,20)
捕捉Error
在swift中,可以使用do-catch捕捉Error。比如下面的例子,通过do-catch去捕获异常,最终会执行catch中的代码。
enum netWorkError: Error {
case businessError(code: Int, msg: String)
case systemError(msg: String)
}
func divNum(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw netWorkError.businessError(code: 300, msg: "除数不能为0")
}
let result = num1 / num2
return result
}
do{
let num = divNum(100,0) // 这一句会发生异常
print(num)
}catch {
print("Error") // 会执行这一句
}
处理Error
在swift中,处理Error的3种方式:
1、通过do-catch捕捉Error,然后处理Error(一般是和定义的枚举结合,通过switch来处理)。
do{
let num = try divNum(100, 0)
print(num)
}catch let error as netWorkError {
switch error {
case .businessError(code: 300, msg: "除数不能为0"):
print("确认---除数不能为0")
case .businessError(let code,let msg):
print(code,msg)
case .systemError(let systemMsg):
print("systemError:",systemMsg)
default:
print("other MyError")
}
}catch {
print("other UnKnow Error")
}
2、不捕捉Error,在当前函数增加throws声明,Error将自动抛给上层函数。如果最终没人处理,系统一样会崩溃闪退。
enum netWorkError: Error {
case businessError(code: Int, msg: String)
case systemError(msg: String)
}
func divNum(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw netWorkError.businessError(code: 300, msg: "除数不能为0")
}
let result = num1 / num2
return result
}
// noHandlerError函数声明了throws,一样没有处理异常,只是往上抛出,看有没有人去处理。
func noHandlerError() throws {
let num = try divNum(100, 0)
print(num)
}
3、通过使用try?、try!调用可能会抛出Error的函数,这样就不用去处理Error。当调用的函数抛出异常是得到的结果就是nil,如果正常,则返回一个可选项。
enum netWorkError: Error {
case businessError(code: Int, msg: String)
case systemError(msg: String)
}
func divNum(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw netWorkError.businessError(code: 300, msg: "除数不能为0")
}
let result = num1 / num2
return result
}
// 通过try?来调用,返回num是nil
var num = try? divNum(100, 0)
print(num)
// 其实try?等价于下面代码的
var a: Int?
do {
a = try divNum(100, 0)
}catch {
a = nil
}
rethrows
rethrows表明:函数本身不会抛出错误,但调用闭包参数抛出错误,那么它会将错误向上抛。
rethrows主要用于参数有闭包的时候,闭包本身会有抛出异常的情况。
rethrows作为一个标志,显示的要求调用者去处理这个异常(不处理往上抛)。
func divNum(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw netWorkError.businessError(code: 300, msg: "除数不能为0")
}
let result = num1 / num2
return result
}
func exec(num1: Int, num2: Int, fn: (Int, Int) throws -> Int) rethrows {
print(try? fn(num1,num2)) // 这里因为fn函数有throws标志,必须用try处理异常
}
// 这里因为exec函数有rethrows标志,所以也必须用try去处理异常
try exec(num1: 100, num2: 200, fn: divNum)
网友评论