一、开发过程中常见的错误
- 语法错误(编译报错)
- 逻辑错误
- 运行时错误(可能会导致闪退)
- ...
二、自定义错误
- Swift中可以通过Error协议自定义运行时的错误
enum SomeError : Error {
case illegalArg(String)
case outOfBounds(Int, Int)
case outOfMemory
}
- 函数内部可以通过throw抛出自定义Error,可能会抛出Error的函数必须加上throws声明
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw SomeError.illegalArg("0 不能作为除数")
}
return num1 / num2
}
var result = try divide(20, 10)
三、do-catch
- 可以使用do-catch捕捉Error
- 抛出Error后,try下一句知道作用域结束的代码都将停止运行
do {
try divide(20, 0)
} catch let error {
switch error {
case let SomeError.illegalArg(msg):
print("参数错误:", msg)
default:
print("其他错误")
}
}
四、处理Error
- 处理Error的两种方式
- 通过do-catch捕捉Error
- 不捕捉Error,在当前函数增加throws声明,Error将自动抛给上次函数
- 如果最顶层函数(main函数)依然没有捕捉Error,那么程序将终止
func test() throws {
print("1")
print(try divide(20, 0))
print("1")
}
五、try?、try!
- 可以使用try?、try!调用可能会抛出Error的函数,这样就不用去处理Error
- try? 如果调用的结果无错误、会将结果包装成一个可选项
- try? 如果调用的结果有错误、会返回nil
- try! 如果调用的结果无错误、会返回解包后的值
- try! 如果有错误,程序终止error: Execution was interrupted, reason: EXC_BREAKPOINT
func test() {
print("1 = ")
print(try? divide(20, 10)) // Optional(2)
print(try? divide(20, 0)) // nil
print(try! divide(20, 20)) // 1
}
test()
// a、b是等价的
var a = try? divide(20, 0)
var b: Int?
do {
b = try divide(20, 0)
} catch { b = nil }
六、rethrows
- rethrows表明:函数本身不会抛出错误,但是调用闭包参数抛出错误,那么它将错误向上抛
func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
print(try fn(num1, num2))
}
七、defer
- defer语句:用来定义以任何方式(抛错误、return等)离开代码前必须执行的代码
- defer语句将延迟至当前作用域结束之前执行
- defer语句的执行顺序和定义顺序相反
func fn1() {print("fn1")}
func fn2() {print("fn2")}
func tests() {
defer { fn1() }
defer { fn2() }
}
tests() // fn2 fn1
八、assert (断言)
- 不符合指定条件就抛出运行时错误,常用语调试(Debug)阶段的条件判断
- 默认情况下、swift的断言智慧在Debug模式下生效、Release模式下会忽略
func divide(_ num1: Int, _ num2: Int) throws -> Int {
assert(num2 != 0, "0 不能作为除数")
return num1 / num2
}
- 增加Swift Flags修改断言的默认行为
- -assert-config Release : 强制关闭断言
- -assert-config Debug : 强制开启断言
九、fatalError
- 如果遇到验证问题,希望结束程序时,可以直接调用fatalError函数抛出错误(这里无法通过do-catch捕捉的错误)
- 使用了fatalError函数,就不需要再写return
func test(_ num: Int) -> Int {
if num >= 0 {
return 1
}
fatalError("num 不能小于0")
}
- 在默写不得不实现,但是不希望别人调用的方法,可以考虑内部使用fatalError函数
十、局部作用域
do {
var dog = Dog()
dog.run()
}
do {
var dog = Dog()
dog.run()
}
网友评论