Original file: Https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_ language/errorhandling.html#//apple_ref/doc/uid/tp40014097-ch42-id508
Reference: http://wiki.jikexueyuan.com/project/swift/chapter2/18_Error_Handling.html
1. Error handling
Error handling is the process of responding to an error and returning from an error. Swift provides first-class error support, including throwing, capturing, transmitting, and controlling recyclable errors at run time.
Some functions and methods are not always guaranteed to execute all code or produce useful output. A nullable type is used to indicate that a value may be empty, but when a function fails, it can often be used to determine the cause of the failure, so the code can respond correctly to the failure.
For example, considering a task that reads and processes data from a file on disk, there are several situations that can cause this task to fail, including files that specify paths that do not exist, files that do not have a readable property, or files that are not encoded in the appropriate format. Distinguishing these errors allows the program to resolve and fix these errors, and, if possible, report these errors to the user.
Note: error handling in Swift involves the error handling style, which uses the Nserror and objective-c in cocoa.
2. Indicates and throws an error
In Swift, the error is ErrorType
represented by a value that conforms to the agreement.
Swift enumeration is especially useful for modeling a series of related errors, associating values that characterize the nature of the error.
For example, you can indicate an error that occurs when you operate an auto-trafficking opportunity:
1 enum Vendingmachineerror:errortype {2 Case invalidselection 3 Case insufficientfunds (coinsneeded:int) 4 Case Outofstock 5 }
In this case, the vending machine may fail for the following reasons: The requested item does not exist, as InvalidSelection
indicated. The price of the requested item is higher than the amount invested, InsufficientFunds
expressed in. The associated double value indicates how much more money is needed to complete the transaction. The requested item has been sold out, with the OutOfStock
expression.
Errors are thrown to let you know that an exception has occurred and that the normal process cannot continue. throws
This function or method can throw an error by adding a keyword after the argument declared by the function or method. For example, a vending machine also requires 5 coins:
Throw 5)
3. Handling Errors
When an error is thrown, the surrounding code environment must handle the error, such as correcting the problem, trying another method, or reporting the error message to the user.
There are four ways to handle errors in Swift. You can pass the error from the function to the code that called the function, or do
-catch语句来处理这个错误,又或者当作一个可选值来处理这个错误,或者断言这个错误不会发生。下面将一一介绍这四种方式。
When a function throws an error, it changes the flow of your program, so it is important to quickly determine where the error is thrown. So, before you call a function, method, or constructor that might throw an error, add the Try keyword (or try? , try! )。
Note: Swift's error handling is similar to other languages, with try
, catch
andthrow等关键字。和很多语言(包括Objective-C)中的异常处理不一样,Swift中的处理不会展开调用堆(性能损耗很大的一个过程)。因此,throw语句的性能和return语句差不多。
(1) Throwing errors through functions
To indicate that a function, method, or constructor might throw an error, add the Throw keyword after the function's arguments.
If the function specifies a return value, the throws
keyword is placed before the return arrow (-).
1 func canthrowerrors () throws, String2 3 func cannotthrowerrors () String
An throwing function throws an error in the body of a function that passes it where it is called.
Note: Only the throw function can pass an error, and the error within the non-throwing function must be handled.
In the following example, if the requested item does not exist, is sold out, or is out of the input amount, the vend(itemNamed:)
function throws an error:
1 structItem {2 var price:int3 var count:int4 }5 6 classVendingmachine {7var inventory = [8 "Candy Bar": Item (Price: A, Count:7),9 "Chips": Item (Price:Ten, Count:4),Ten "Pretzels": Item (Price:7, Count: One) One ] Avar coinsdeposited =0 - func Dispensesnack (snack:string) { -Print"dispensing \ (snack)") the } - - func vend (itemnamed name:string) throws { -Guard var item = Inventory[name]Else { + Throwvendingmachineerror.invalidselection - } + AGuard Item.count >0 Else { at ThrowVendingmachineerror.outofstock - } - -Guard Item.price <= coinsdepositedElse { - ThrowVendingmachineerror.insufficientfunds (CoinsNeeded:item.price-coinsdeposited) - } in -coinsdeposited-=Item.price to--Item.count +Inventory[name] =Item - dispensesnack (name) the } *}
First, the guard
condition is detected with a statement, and if the condition is not met, an error is thrown and the function is rolled out. because throw
The statement will change the program flow immediately, and the item will be sold when all the purchase conditions (the item exists, the inventory is sufficient, and the input amount is sufficient) are met.
When calling a throw function, precede the call with the try
. This keyword indicates that the function can throw an error, and that the try
code will not be executed later.
Because the Vend (itemnamed:) function passes the thrown error, you must directly handle the error--with do
-- catch
statement, try?
or, if you call this method in code.try!,或者继续传递错误。
For example, the Buyfavoritesnack (_:vendingmachine:) function in the following example is also a throw function,vend(itemNamed:)函数抛出的错误将会在传递到buyFavoriteSnack(_:vendingMachine:)被调用的地方。
1Let Favoritesnacks = [2 "Alice":"Chips",3 "Bob":"Licorice",4 "Eve":"Pretzels",5 ]6 func buyfavoritesnack (person:string, vendingmachine:vendingmachine) throws {7Let Snackname = Favoritesnacks[person]??"Candy Bar"8 Tryvendingmachine.vend (itemnamed:snackname)9}
buyFavoriteSnack(_:vendingMachine:)函数根据人名查询最喜爱的物品,并调用vend(itemNamed:)尝试购买。由于vend(itemNamed:)可能抛出一个错误,调用前加try关键字。
(2) Handling Errors with do-catch statements
You can use Do-catch to execute code blocks to handle errors. If the code in the Do code block throws an error and matches the list of errors in the catch clause, the error can be handled.
The format of a do-catch statement a catch
clause contains a catch
keyword, followed by one pattern
to match the error and the corresponding execution statement. :
1 do try< /span> expression statements 4 } catch pattern Span style= "color: #800080;" >1 { 5 statements 6 } 2 condition { 7 statements 8 }
In order to ensure that the error is handled, a band pattern
of clauses is used catch
to match the error. If a catch
clause does not specify a style, the clause matches and binds any error to a local error
constant.
The catch clause does not have to handle any errors that may be thrown in the DO clause. If an error is not handled by an arbitrary catch clause, the error is passed to the external domain. In any case, this error must be handled in an external domain, perhaps with a closed do
-catch子句处理,或者传递到一个抛出函数里。
1var vendingmachine =Vendingmachine ()2vendingmachine.coinsdeposited =83 Do {4 TryBuyfavoritesnack ("Alice", Vendingmachine:vendingmachine)5}Catchvendingmachineerror.invalidselection {6Print"Invalid Selection.")7}CatchVendingmachineerror.outofstock {8Print"Out of Stock.")9}Catchvendingmachineerror.insufficientfunds (Let coinsneeded) {TenPrint"insufficient funds. Please insert an additional \ (coinsneeded) coins.") One } A //prints "insufficient funds. Please insert an additional 2 coins. "
In the example above, the vend(itemNamed:)
function try
is called in the expression because the function throws an error. If an error is thrown, the program execution process immediately goes to the catch
clause and determines in the catch
clause whether the error delivery continues to be transmitted. If no error is thrown, the remaining statements in the statement will be executed do
.
(3) Convert the error to an optional value
can be usedtry?来处理错误,这种方式把错误转化成可选值。如果一个错误在try?表达式中被抛出,这个表达式的值将为nil。
1Func somethrowingfunction () throwsInt {2 // ...3 }4 5Let x =Try?somethrowingfunction ()6 7Let Y:int?8 Do {9y =Trysomethrowingfunction ()Ten}Catch { Oney =Nil A}
If Somethrowingfunction () throws an error, the value of x or Y is nil. Otherwise, the value of x or Y equals the return value of the function. Note that the types of x and Y are selectable for the return type of the function.
When you want to handle all the errors in the same way, try? It allows you to easily write a precise error-handling method.
1 func fetchdata () Data? {2 if Try return Data} 3 if Try return Data} 4 return Nil 5 }
(4) Disable error delivery
Sometimes you know that a throw function actually runs without throwing an error. In this case, you can precede the expression to suppress error delivery by addingtry!关键字,并且把这个调用包装在一个断言里,判断是否没有任何错误抛出。如果抛出了错误,将产生一个运行时错误。
In the following example, a picture resource is loaded through the specified path, and an error is thrown if the picture cannot be loaded. In fact, this image is stored in the application's resources, and the runtime does not produce an error, so you can suppress incorrect delivery.
1 Try! LoadImage ("./resources/john appleseed.jpg")
(5) Specify the closing action
Executes a series of statements with the defer statement before the end of the current code block run. Regardless of how the code block ends (whether it's throwing an error, or return, break), the defer statement can perform some necessary actions. For example, you can use the defer statement to ensure that the file descriptor is closed and the memory is freed manually.
defer
Statement to defer execution until you exit the current domain. defer
The statement includes defer
the keyword and the statement to be executed later. The deferred statement may not contain any code that transfers the execution process to the outside, such break
as return
a statement, or by throwing an error. The execution order of deferred operations is reversed from the order in which they are defined, that is, the code in the first defer
statement defer
executes after the code in the second statement.
1 func Processfile (filename:string) throws {2 ifexists (filename) {3Let file =open (filename)4 Defer {5 Close (file)6 }7 whileLet line =TryFile.readline () {8 //Work with the file.9 }Ten //Close (file) is called here, at the end of the scope. One } A}
The above example uses the defer statement to ensure that the open (_:) function must call the corresponding close (_:) function.
Note: You can also use the defer statement even if there is no error handling code.
Swift2.1 Syntax Guide-error handling