在OC中,单元测试时我们会使用断言,断言中条件满足时会产生异常,并打印出相应的断言错误。而在Swift对异常的处理和抛出也可以像其他语言一样处理。
//简单的异常使用枚举定义,但是枚举要继承Error协议,这里写两个异常, 没油, 超重
enum CarError: Error{
case lackOil
case overload
}
//定义汽车是否能驾驶
enum Driver {
case start//能否启动
case loading//能否载重
}
//货车类,两个属性,
//最少的油量,少于10%货车就不能启动。
//最大载重量,大于2000就不能工作
class Car {
var minOil: Double = 0.1
var maxCargo: Double = 2000.0// kg
//throws 表示该方法会出现异常,不然不能被放在do里面
func drivering(driver: Driver)throws {//开车
switch driver {
case .start:
//guard else 语句类似于if else 语句, guard 后面的条件通过执行后面的语句, 不通过执行 else 里面的语句
guard self.minOil > 1.0 else {
throw CarError.lackOil // 抛出异常 返回上一调用方法,在catch里面找异常处理
}
print("the car begin move")
case .loading:
guard self.maxCargo < 2000 else {
throw CarError.overload
}
print("the car begin working")
}
}
//现在我们写一个处理异常的方法,
func workingCar(car: Car)throws {
//defer 关键字是在这个方法调用结束后一定会调用的方法。也是最后走的方法
defer {
print(" always run")
}
// do catch 在do闭包里面执行会抛出异常的代码,在catch 分支里面匹配异常处理异常, 在do 里面的调用都是throws 标记后的方法,意思是这个方法可能会出现异常
// try! 使用try! 是我们确定这个调用不会发生异常 如果有异常,就会崩溃。一般不这么用
//try 使用try 表示调用的方法会出现异常, 还有 try?调用了一个会出现异常的方法,并且结果转换为一个Optional, 异常返回nil
do {
//下面的调用是只要上一个出现异常,就不会继续调用下面的方法哦
try car.drivering(driver: .loading)
try car.drivering(driver: .start)
} catch let CarError.lackOil {
//对异常的处理
print(" lack of oil ")
} catch let CarError.overload {
print(" overLoad ")
}
}
//最后我们调用一下
let car = Car.init(oil: 0.5, cargo: 3000)
do {
try workingCar(car: car)
} catch {
}
就会打印:
the car begin move
** overLoad **
** will will**
//再调用一下
let car = Car.init(oil: 0.05, cargo: 1500)
do {
try workingCar(car: car)
} catch {
}
打印:
** lack of oil**
** will will**
因为缺油所以再抛出油量不够的异常后,后面的是否超重方法不在执行,但是will will 依然会执行
其实OC里面的异常处理我机会没有主动处理过,实在是难理解,一般都直接打印一下就不管了,并且一般看见error传个nil。如果你想看关于OC的异常处理,可以看这个NSError:http://nshipster.com/nserror/。