Swift17-错误处理

表示并抛出错误、处理错误、指定清理操作。

错误处理是响应错误以及从错误中恢复的过程。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