异常处理
作者:互联网
语法错误:就平时写程序的时候会报的错误,在编译之前就得处理掉
逻辑错误:代码写错了,比如加写成-了
运行时错误
程序员日常解决最多的错误应该就是运行时错误了,跑着跑着不知道为毛挂了,然后就开始打断点做各种调试
func divide(dividend:Int,divisor:Int) -> Int {
return dividend / divisor
}
print(divide(dividend: 20, divisor: 0))
在非自定义错误的情况下可以做如下处理
func divide(dividend:Int,divisor:Int) -> Int? {
if divisor == 0 {
return nil
}
return dividend / divisor
}
print(divide(dividend: 20, divisor: 0))
比如返回一个可选类型,处理在0的时候返回nil,这样后面判断一下这个可选类型就好了
自定义错误
捕获到错误了之后的自定义错误
struct MyError: Error {
var errorCode:String
}
func divide(dividend:Int,divisor:Int) throws -> Int? {
if divisor == 0{
throw MyError(errorCode: "除数不能是0")
}
return dividend / divisor
}
var result = try divide(dividend: 10, divisor: 0)
print(result)
比如这里面就是一个自定义的错误,自定义错误是一个协议,所以枚举 结构体 类都可以继承,一般来说为了省空间可以考虑枚举,因为枚举实际占用字节是1个字节,如果是要报错的字符串,也最好用结构体,实际占用8个字节,如果用类的话实际占用就大很多了,指针是8个字节,里面是类信息最起码就16个字节,元类信息占用空间更大,所以能不用类尽量别用
do-catch
上面的代码运行会报错,原因就是没有处理这个异常,Swift处理异常就是do-Catch语法
struct MyError: Error {
var errorCode:String
}
func divide(dividend:Int,divisor:Int) throws -> Int? {
if divisor == 0{
throw MyError(errorCode: "除数不能是0")
}
return dividend / divisor
}
func fn1()
{
do {
try divide(dividend: 20, divisor: 0)
} catch let myError as MyError {
print(myError.errorCode)
} catch
{
print("catch到未知错误")
}
}
fn1()
错误链
enum MyError: Error {
case errorCode(String)
case outOfBounds(Int,Int)
}
func divide(dividend:Int,divisor:Int) throws -> Int? {
if divisor == 0{
throw MyError.errorCode("除数不能是0")
}
return dividend / divisor
}
func fn1() throws
{
try divide(dividend: 20, divisor: 0)
}
func fn2() throws
{
try fn1()
}
do {
try fn2()
} catch let MyError.errorCode(errorCode) {
print(errorCode)
}catch let MyError.outOfBounds(index,limit)
{
print("index:\(index) out of \(limit)")
}
假如在下层函数不用处理,也可以把错误往上抛,直到主函数,不过主函数不处理就会报错了
try? try!
func divide(dividend:Int,divisor:Int) throws -> Int? {
if divisor == 0{
throw MyError.errorCode("除数不能是0")
}
return dividend / divisor
}
let result = try? divide(dividend: 10, divisor: 0)
print(result)
try?和try!的区别只在使用上面,本质就是把错误转为可选项,如果有错误就返回nil
retrows
enum MyError: Error {
case errorCode(String)
case outOfBounds(Int,Int)
}
func divide(dividend:Int,divisor:Int) throws -> Int {
if divisor == 0{
throw MyError.errorCode("除数不能是0")
}
return dividend / divisor
}
func fn1(fn:(Int,Int) throws -> Int, a:Int , b:Int) rethrows
{
print(try fn(a,b))
}
do {
try fn1(fn: divide, a: 10, b: 0)
} catch let MyError.errorCode(errorCode) {
print(errorCode)
}
当如果传入的闭包函数有问题,这个类也不准备处理的时候就用rethrows把错误传到更上一级的函数
defer
struct LengthError:Error {
var des:String
}
func open(path:String) -> Int
{
print("打开")
return 0
}
func read(length:Int,sign:Int) throws -> String
{
if(length > 1000)
{
throw LengthError(des:"太长了")
}
return "content"
}
func close()
{
print("关闭")
}
func readBook() throws
{
let sign = open(path: "123")
try read(length: 1001, sign: sign)
close()
}
try? readBook()
假如这是个读取代码,因为长度超过了1000函数不支持,抛出异常,这种情况来说,close()就不会调用了,因为异常之后的代码就不会执行了
func readBook() throws
{
let sign = open(path: "123")
defer
{
close()
}
try read(length: 1001, sign: sign)
}
假如加上了defer就会在该作用域结束前调用,比如这个就是在readBook结束之前调用,所以即使抛出异常也会执行关闭
注意点:
func readBook() throws
{
let sign = open(path: "123")
defer{ print("1") }
defer{ print("2") }
defer{ print("3") }
try read(length: 1001, sign: sign)
}
同一个defer是从上往下,但不同的defer先声明的执行越晚,比如上面来说结果是3,2,1
标签:try,divisor,处理,errorCode,Int,func,dividend,异常 来源: https://blog.csdn.net/yokan_de_s/article/details/116098561