表示并抛出错误、处理错误、指定清理操作。
错误处理是响应错误以及从错误中恢复的过程。Swift提供了在运行时对可恢复错误的抛出、捕获、传递和操作的一等支持。
某些操作无法保证总是执行完所有代码或总是生成有用的结果。可选类型可用来表示值确实,但是当某个操作失败时,最好能得知失败的原因,从而可以作出相应应对。
表示并抛出错误:
在Swift中,错误用符合Error协议的类型的值来表示。这个空协议表明该类型可以用于错误处理。
Swift的枚举类型尤为何时构建一组相关的错误状态,枚举的关联值还可以提供错误状态的额外信息。
enum TestError:Error{
case erroeOne,errorTwo
}
抛出一个错误可以让你表明有意外情况发生,导致正常的执行流程无法继续执行。抛出错误使用throw关键字。
处理错误:
某个错误被抛出时,附近的某部分代码必须负责处理这个错误。
Swift中有4种处理错误的方式。可以把函数抛出的错误传递给调用此函数的代码、用do-catch语句处理错误、将错误作为可选类型处理、或者断言此错误根本不会发生。
在调用一个能抛出错误的函数、方法或者构造器之前,加上try关键字,或者try?或try!这种变体。
用throwing函数传递错误:
为了表示一个函数、方法或构造器可以抛出错误,在函数声明的参数列表之后加上throws关键字。一个标有throws关键字的函数被称作throwing函数。如果这个函数指明了返回值类型,throws关键词需要写在箭头(->)的前面。
func name()throws->returnType{...}
一个throwing函数可以在其内部抛出错误,并将错误传递到函数被调用时的作用域。
注意:只有throwing函数可以传递错误。任何在某个非throwing函数内部抛出的错误只能在函数内部处理。
throwing函数可以是构造器,throwing构造器也能传递错误。
init()throws{...}
用do-catch处理错误:
可以使用一个do-catch语句运行一段闭包代码来处理错误。如果在do子句中的代码抛出了一个错误,这个错误会与catch子句做匹配,从而决定哪条子句能处理它。
do{
try expression
statements
}catch pattern 1{
statements
}catch pattern2 where condition{
statements
}
在catch后面写一个匹配模式来表明这个子句能处理什么样的错误。如果一条catch子句没有指定匹配模式,那么这条子句可以匹配任何错误,并且把错误绑定到一个名字为error的局部变量。
catch子句不必将do子句中的代码所抛出的每一个可能的错误都作处理。如果所有catch子句都未处理错误,错误就会传递到周围的作用域。然而,错误还是必须要被某个周围的作用域处理的---要么是一个外围的do-catch错误处理语句,要么是一个throwing函数的内部。
将错误转换成可选值:
可以使用try?通过将错误转换成一个可选值来处理错误。如果在评估try?表达式时一个错误被抛出,那么表达式的值就是nil。
func someThrowingFunc()throws->Int{
//...
}
let x=try?someThrowingFunc()
//这里如果someThrowingFunc抛出错误,则x赋值为nil
//这条语句相当于
let y:Int?
do{
y=try someThrowingFunc()
}catch{
y=nil
}
禁用错误传递:
有时知道某个throwing函数实际上在运行时是不会抛出错误的,在这种情况下,可以在表达式前面写 try! 来禁用错误传递,这会把调用包装在一个不会有错误抛出的运行时断言中。如果真的抛出了错误,你会得到一个运行时错误。
let photo=try! loadImage(atPath:".....")
指定清理操作:
可以使用defer语句在即将离开当前代码块时执行一系列语句。该语句让你能执行一些必要的清理工作,不管是以何种方式离开当前代码块----无论是由于抛出错误而离开,还是由于诸如return或者break的语句。
例如:可以用defer语句来确保文件描述符得以关闭,以及手动分配的内存得以释放。
defer语句将代码的执行延迟到当前的作用域退出之前。该语句由defer关键字和要被延迟执行的语句组成。延迟执行的语句不能包含任何控制转移语句,例如break或是return语句,或是抛出一个错误。
func processFile(filename:String)throws{
if exists(filename){
let file=open(filename)
defer{
close(file)
}
while let line=try file.readline(){
//处理文件
}
//close(file)会在这里被调用,即作用域的最后
}
}
注意:即使没有涉及到错误处理,也可以使用defer语句。
原文:https://www.cnblogs.com/cjj-ggboy/p/12861038.html