SwiftSwiftswift

swift异常处理(Error)

2021-03-24  本文已影响0人  三国韩信

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)

上一篇下一篇

猜你喜欢

热点阅读