Swift-错误处理
2022-08-16 本文已影响0人
Sweet丶
Swift错误处理.png
一、Swift中抛出自定义Error
有时定义一个方法,这个方法在执行的过程中可能会抛出异常,这个时候需要向调用者抛出,让调用者来具体处理,比如系统的JSONSerialization.jsonObject方法。下面是一个抛出自定义异常的例子:
// 1.先自定义一个错误类型,类型需要遵守Error协议,比如自定义枚举。
enum SomeError : Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
// 2. 在会抛出错误的方法中声明throws,并且在需要的地方抛出对应的错误
/// 自定义Error的抛出
static func divide_error(_ v1: Int, _ v2: Int) throws -> Int {
if v2 == 0 {
throw SomeError.illegalArg("0不能作为除数")
}else if v1 < v2 {
throw SomeError.outOfBounds(v1, v2)
}else if v1 > Int8.max || v2 > Int8.max{// 大于Int8以上的数据不作除法
throw SomeError.outOfMemory
}else{
return v1/v2
}
}
/// 如果调用divide_error的地方对于抛出的错误不catch,那么会向上一级作用域抛出,
/// 如果直到系统main函数都未catch,那么会发生闪退fatal error.
// 3. 调用会抛出异常的方法一
do {
let result1 = try divide_error(10, 5)
// let result2 = try divide_error(10, 0)
// let result3 = try divide_error(10, 20)
// let result4 = try divide_error(Int.max, 50)
} catch SomeError.outOfMemory {
print("捕获到了超出最大值的异常")
} catch SomeError.illegalArg(let errorMsg){
print(errorMsg)
} catch let SomeError.outOfBounds(num1, num2){
print("除数大于被除数:num1=\(num1), num2 =\(num2)")
} catch {
print("其它异常")
}
二、将错误抛出给上一级调用者处理
如果在调用方法时,不能确定抛出错误的具体处理,而是要在上一层调用才能明确,这个时候可以将错误继续向上一层抛出,如果直到系统main函数都未catch,那么会发生闪退fatal error. 具体写法:
// 4. 调用上述会抛出异常的方法二: 将错误向上抛出
// 在设计一个方法时,方法内部调用了会抛出异常的方法,
// 但是抛出的这个异常的处理是希望使用者来决定,
// 这个时候就可以继续向上抛出,即自己的方法写上throws,调用时不do...catch
func test1() throws {
let result1 = try divide_error(10, 5)
}
func test0() throws {
let result1 = try test1()
}
// 程序员在外部调用方法负责去catch
do {
try test0()
} catch is SomeError {
print("SomeError")
}
三、try?、try!
使用try?和try!来调用可能抛出错误的函数时,可以不向上抛出或者不使用do...catch。
// 方式一
var a = try? divide_error(10, 0)
// 方式二:等价于方式一
var b: Int?
do {
b = try divide_error(10, 0)
} catch {}
// a和b的值都是nil
// 方式三:使用try!, 效果是对try?的结果强制解包,有crash风险
四、rethrows
如果函数的一个参数是可能抛出错误的闭包,那么这个时候函数想将错误抛出,需要用rethrows表明。
/// 这个是系统的空合并运算符的定义
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
五、defer
这个关键字用来定义以任何形式(包括抛出错误、return)离开代码块前都要执行的语句, 程序发生crash不算,因为crash时已经是停在某行代码了,无法继续运行。
func test() throws {
defer {
print("defer1----")
}
// 多个defer时,打印是defer2在前
defer {
print("defer2----")
}
// return
var a = try divide_error(10, 0)
}
六、assert、fatalError
assert:一般用于debug阶段,在运行时抛出不符合条件的错误。在release模式下会直接失效。
fatalError:直接抛出错误,让程序崩溃。
// 第一个参数表示
assert(delegate != nil, "NetWorkConfig setDelegate success")
// 自定义view时,必须实现的方法
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}