Error

110 阅读1分钟
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、isas使用

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)
}