@@ -699,6 +699,213 @@ let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
699699 ```
700700-->
701701
702+ ## Specifying the Error Type
703+
704+ All of the examples above use the most common kind of error handling,
705+ where the errors that your code throws
706+ can be values of any type that conforms to the ` Error ` protocol.
707+ This approach matches the reality that
708+ you don't know ahead of time every error that could happen
709+ while the code is running,
710+ especially when propagating errors thrown somewhere else.
711+ It also reflects the fact that errors can change over time.
712+ New versions of a library ---
713+ including libraries that your dependencies use ---
714+ can throw new errors,
715+ and the rich complexity of real-world user configurations
716+ can expose failure modes that weren't visible during development or testing.
717+ The error handling code in the examples above
718+ always includes a default case to handle errors
719+ that don't have a specific ` catch ` clause.
720+
721+ Most Swift code doesn't specify the type for the errors it throws.
722+ However,
723+ you might limit code to throwing errors of only one specific type
724+ in the following special cases:
725+
726+ - When running code on an embedded system
727+ that doesn't support dynamic allocation of memory.
728+ Throwing an instance of ` any Error ` or another boxed protocol type
729+ requires allocating memory at runtime to store the error.
730+ In contrast,
731+ throwing an error of a specific type
732+ lets Swift avoid heap allocation for errors.
733+
734+ - When the errors are an implementation detail of some unit of code,
735+ like a library,
736+ and aren't part of the interface to that code.
737+ Because the errors come from only the library,
738+ and not from other dependencies or the library's clients,
739+ you can make an exhaustive list of all possible failures.
740+ And because these errors are an implementation detail of the library,
741+ they're always handled within that library.
742+
743+ - In code that only propagates errors described by generic parameters,
744+ like a function that takes a closure argument
745+ and propagates any errors from that closure.
746+ For a comparison between propagating a specific error type
747+ and using ` rethrows ` ,
748+ see < doc:Declarations:Rethrowing-Functions-and-Methods > .
749+
750+ For example,
751+ consider code that summarizes ratings
752+ and uses the following error type:
753+
754+ ``` swift
755+ enum StatisticsError : Error {
756+ case noRatings
757+ case invalidRating (Int )
758+ }
759+ ```
760+
761+ To specify that a function throws only ` StatisticsError ` values as its errors,
762+ you write ` throws(StatisticsError) ` instead of only ` throws `
763+ when declaring the function.
764+ This syntax is also called * typed throws*
765+ because you write the error type after ` throws ` in the declaration.
766+ For example,
767+ the function below throws ` StatisticsError ` values as its errors.
768+
769+ ``` swift
770+ func summarize (_ ratings : [Int ]) throws (StatisticsError) {
771+ guard ! ratings.isEmpty else { throw .noRatings }
772+
773+ var counts = [1 : 0 , 2 : 0 , 3 : 0 ]
774+ for rating in ratings {
775+ guard rating > 0 && rating <= 3 else { throw .invalidRating (rating) }
776+ counts[rating]! += 1
777+ }
778+
779+ print (" *" , counts[1 ]! , " -- **" , counts[2 ]! , " -- ***" , counts[3 ]! )
780+ }
781+ ```
782+
783+ In the code above,
784+ the ` summarize(_:) ` function summarizes a list of ratings
785+ expressed on a scale of 1 to 3.
786+ This function throws an instance of ` StatisticsError ` if the input isn't valid.
787+ Both places in the code above that throw an error
788+ omit the type of the error
789+ because the function's error type is already defined.
790+ You can use the short form, ` throw .noRatings ` ,
791+ instead of writing ` throw StatisticsError.noRatings `
792+ when throwing an error in a function like this.
793+
794+ When you write a specific error type at the start of the function,
795+ Swift checks that you don't throw any other errors.
796+ For example,
797+ if you tried to use ` VendingMachineError ` from examples earlier in this chapter
798+ in the ` summarize(_:) ` function above,
799+ that code would produce an error at compile time.
800+
801+ You can call a function that uses typed throws
802+ from within a regular throwing function:
803+
804+ ``` swift
805+ func someThrowingFunction () -> throws {
806+ let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
807+ try summarize (ratings)
808+ }
809+ ```
810+
811+ The code above doesn't specify an error type for ` someThrowingFunction() ` ,
812+ so it throws ` any Error ` .
813+ You could also write the error type explicitly as ` throws(any Error) ` ;
814+ the code below is equivalent to the code above:
815+
816+ ``` swift
817+ func someThrowingFunction () -> throws (any Error ) {
818+ let ratings = [1 , 2 , 3 , 2 , 2 , 1 ]
819+ try summarize (ratings)
820+ }
821+ ```
822+
823+ In this code,
824+ ` someThrowingFunction() ` propagates any errors that ` summarize(_:) ` throws.
825+ The errors from ` summarize(_:) ` are always ` StatisticsError ` values,
826+ which is also a valid error for ` someThrowingFunction() ` to throw.
827+
828+ Just like you can write a function that never returns
829+ with a return type of ` Never ` ,
830+ you can write a function that never throws with ` throws(Never) ` :
831+
832+ ``` swift
833+ func nonThrowingFunction () throws (Never) {
834+ // ...
835+ }
836+ ```
837+ This function can't throw because
838+ it's impossible to create a value of type ` Never ` to throw.
839+
840+ In addition to specifying a function's error type,
841+ you can also write a specific error type for a ` do ` -` catch ` statement.
842+ For example:
843+
844+ ``` swift
845+ let ratings = []
846+ do throws (StatisticsError) {
847+ try summarize (ratings)
848+ } catch {
849+ switch error {
850+ case .noRatings :
851+ print (" No ratings available" )
852+ case .invalidRating (let rating):
853+ print (" Invalid rating: \( rating ) " )
854+ }
855+ }
856+ // Prints "No ratings available"
857+ ```
858+
859+ In this code,
860+ writing ` do throws(StatisticsError) ` indicates that
861+ the ` do ` -` catch ` statement throws ` StatisticsError ` values as its errors.
862+ Like other ` do ` -` catch ` statements,
863+ the ` catch ` clause can either handle every possible error
864+ or propagate unhandled errors for some surrounding scope to handle.
865+ This code handles all of the errors,
866+ using a ` switch ` statement with one case for each enumeration value.
867+ Like other ` catch ` clauses that don't have a pattern,
868+ the clause matches any error
869+ and binds the error to a local constant named ` error ` .
870+ Because the ` do ` -` catch ` statement throws ` StatisticsError ` values,
871+ ` error ` is a value of type ` StatisticsError ` .
872+
873+ The ` catch ` clause above uses a ` switch ` statement
874+ to match and handle each possible error.
875+ If you tried to add a new case to ` StatisticsError `
876+ without updating the error-handling code,
877+ Swift would give you an error
878+ because the ` switch ` statement wouldn't be exhaustive anymore.
879+ For a library that catches all of its own errors,
880+ you could use this approach to ensure any new errors
881+ get corresponding new code to handle them.
882+
883+ If a function or ` do ` block throws errors of only a single type,
884+ Swift infers that this code is using typed throws.
885+ Using this shorter syntax,
886+ you could write the ` do ` -` catch ` example above as follows:
887+
888+ ``` swift
889+ let ratings = []
890+ do {
891+ try summarize (ratings)
892+ } catch {
893+ switch error {
894+ case .noRatings :
895+ print (" No ratings available" )
896+ case .invalidRating (let rating):
897+ print (" Invalid rating: \( rating ) " )
898+ }
899+ }
900+ // Prints "No ratings available"
901+ ```
902+
903+ Even though the ` do ` -` catch ` block above
904+ doesn't specify what type of error it throws,
905+ Swift infers that it throws ` StatisticsError ` .
906+ You can explicitly write ` throws(any Error) `
907+ to avoid letting Swift infer typed throws.
908+
702909## Specifying Cleanup Actions
703910
704911You use a ` defer ` statement to execute a set of statements
0 commit comments