Swift进化到2.0的时候就基本成型了。这里会集中介绍一下2.0和之前版本的不同之处。这也就是plus的含义。
try-catch
在其他语言里基本都用try-catch
来处理异常。之前的swift一直都是沿用了ObjC的一场处理方式:把一个nil的error指针执行取地址以后扔进去,有异常了自己初始化赋值。没有的话就不用管。
try-catch
从字面的意思理解就是“试试这个东西,如果有问题就做别的”。Swift用枚举来定义不同的异常,这样可以保证每次捕捉的异常是唯一的,就像switch语句一样。所以,你可以像下面这样自定义一组异常类型:
enum MyError: ErrorType {
case MissingParameterError
case TypeCastError
case NetworkError
}
注意自定义异常需要在内置的ErrorType上。这是必须的。
你定义好自己的异常enum之后,下面就可以聊一下throws
,try
,do
和catch
了。
首先,throw
关键字加在swift方法的后面来告诉调用者,这个方法可能会失败。这个关键字就加在返回类型的前面:
func accessNetwork() throws -> String{}
有了throw
关键字的修饰之后,这个方法就不可以直接调用了。Xcode会编译不过。在方法内部如何抛出异常呢?请看下面的示例:
func accessNetwork() throws -> String {
print("start access network")
throw MyError.NetworkError
return "response from network"
}
在这个方法里的print用来打印输出,好想这个方法做了什么。
上文说到,带有throw
关键字修饰的方法不能直接调用。那么该怎么用呢?
try accessNetwork()
把try
放在要抛出异常的方法的前面。这样就表明:“我明白这个方法可能会调用失败”。但是只有try
关键字还是不够的,出错了怎么处理呢?所以还是需要do
和catch
关键字。例如:
do {
try accessNetwork()
print("success")
} catch {
print("access network Failed")
}
这是一个比较基本的示范。catch
并不区分不同的异常种类,不管抛出的异常是什么类型都捕获并处理。那么如何具体的处理各种不同的异常呢?在catch
后面指定要处理的类型。
do {
try accessNetwork()
print("success")
} catch MyError.NetworkError {//处理NetworkError异常
print("access network Failed")
} catch {
// 处理全部未被处理的异常
}
除了try-catch之外还有一个简写的异常处理办法:try?
和try!
。使用try?
修饰方法调用。表示“如果调用方法throw了异常,那么就返回nil”。如果你十分确定调用的方法不会抛出任何的异常,那么你可以用try!
。但是,如果这个方法有异常抛出来了,那么Crash。
清理现场。在做完所有的操作后你可能需要一个清理的操作。使用defer
关键字来指定这个清理操作。比如上面的例子中,连接网络获取数据,存储之后关闭网络连接。
func closeNetwork() {
// close
}
func accessNetwork() throws -> String {
print("start access network")
defer {
closeNetwork()
}
throw MyError.MissingParameterError
try storeData()
return "data from network"
}