class MyError: Error {
var msg: String
}
或者:
struct CustomError: Error {
var msg: String
}
enum SomeError: Error {
case illegaArg(String)
case outOfBound(Int, Int)
case outOfMemory
}
throw 抛出自定义Error, 可能会抛出Error的函数必须加上throws声明
func divide(_ num1: Int, _ num2: Int) throws -> Int {
if num2 == 0 {
throw SomeError.illegaArg("0不能作为除数")
}
return num1 / num2
}
处理抛出的Error, 可能抛出异常前使用try
1、do-catch捕捉Error
func test() {
do {
print(try divide(20, 0)) // 一旦在此抛出异常,在其作用域内后的代码都不会执行了
print("不会执行")
} catch let SomeError.illegaArg(msg) {
print("参数异常:", msg)
} catch let SomeError.outOfBound(size, index) {
print("下标越界:", "size=\(size)", "index=\(index)")
} catch SomeError.outOfMemory {
print("内存溢出")
} catch {
print("其他错误")
}
}
2、不处理异常,直接使用throws将异常抛给调用的上层函数,如果上层依然没有捕捉异常,则会crash
func test() throws {
print(try divide(20, 0))
print("不会执行")
}
3、is 、 as使用
func test() {
do {
print(try divide(20, 0))
print("不会执行")
} catch let error as SomeError {
print(error)
} catch {
print("其他错误")
}
}
do {
print(try divide(20, 0))
print("不会执行")
} catch is SomeError {
print("SomeError")
} catch {
print("其他错误")
}
3、 使用try? try!调用可能会抛出异常的函数,就不用处理异常了
func test() {
var r1 = try? divide(20, 10) // Optional(2), Int?
var r2 = try? divide(20, 0) // nil, 捕捉到异常也不会赋值给r2
var r3 = try! divide(20, 10) // 2, Int
}
4、defer 在函数结束前必须要执行的代码,相当于 finally
func handleFile(_ fileName: String) throws {
let file = open(fileName)
defer {
close(fileName)
}
try divide(20, 0)
}