Swift error and exception handling---South Peak sub

Source: Internet
Author: User

Exceptions (Exception) and errors (error).

In OBJECTIVE-C development, an exception is often caused by a programmer's error, such as when we send this message to an object that cannot respond to a message NSObject  , get NSInvalidArgumentException  an exception, and tell us "unrecognized selector Sent to instance "; When we try to access an element by using a subscript that exceeds the number of array elements NSArray  , we get it NSRangeException  . Problems such as the inability of the program to run should be addressed in the development phase, and should not be present in the actual product. By contrast, the NSError  errors represented by more refer to those "reasonable" situations that may be encountered by the user in the app: such as a user name password verification mismatch when logging in, or a problem when trying to read data from a file to generate NSData  objects (such as files that have been accidentally modified) and so on.

However NSError  , the use of the method in disguise encourages developers to ignore errors. Think about what we do when we use an API with an error pointer. We will generate and pass in the API call NSError  to determine if the call failed. As a user of a method that might produce an error, we NSErrorPointer  store the error message in the same way that the pointer was passed in, and then read the content after the call and confirm whether an error occurred. For example, in Objective-c, we would write code like this:

  nserror *< Span class= "PLN" >error;= [data Writetofile: path Options: options Error: &error];if (error{ //there was an error }    

This is great, but there's a problem: In most cases, there's no error in this approach, and many engineers are trying to make it easier and simpler by setting the error of the input nil  , which means they don't care about errors (because they may never have seen the API return errors or how to handle them). So the call becomes this:

[data writeToFile: path options: options error: nil];

But in fact this API call is going to go wrong, for example, when the disk space of the device is full, the write will fail. But when this error comes up and makes your app awkward, you'll almost never start debugging-because the system tried to tell you that something was wrong, but you chose to ignore it.

In Swift 2.0, Apple introduced an exception mechanism for this language. Now, these APIs with NSError  pointers as parameters are changed to the form of exceptions that can be thrown. For example, the above writeToFile:options:error:  , in Swift has become:

public func writeToFile(path: String, options writeOptionsMask: NSDataWritingOptions) throws

When we use this API, we no longer pass in an error pointer as before to wait for the method to fill, but instead become using the try catch  statement:

do { try  D. ( "Hello" , options : []) } Span class= "KWD" >catch let error as nserror {   ( "Error: \ (error.domain)" ) }             

If you do not use try  it, you cannot invoke writeToFile:  the method, it generates a compilation error, which makes it impossible for us to inadvertently ignore these errors. In the above example, the exception that is catch  thrown (here is a NSError  ) is type-cast with Let, which is primarily aimed at Cocoa existing APIs and is a compromise of history. For our newly-written API to throw exceptions, we should throw out an implemented ErrorType  type, which is enum  very appropriate, for example:

Enum LoginError: ErrorType { Case Usernotfound, Userpasswordnotmatch}Func Login(User: String,Password: String) Throws { Users are [string:string], store [user name: password] If !Users.Keys.Contains(User) { throw loginerror< Span class= "pun". usernotfound } if Users[user]!= password { throw< Span class= "PLN" > loginerror. Userpasswordnotmatch } print }          /span>                

This ErrorType  can point out the problem very clearly. At invocation time, the catch  statement is essentially a pattern match:

Do {      TryLogin("Onevcat",Password: "123")} catch loginerror< Span class= "pun". usernotfound { print< Span class= "pun" > ( "Usernotfound" } catch loginerror. Userpasswordnotmatch { print  ( "Userpasswordnotmatch" )  }//do something with login user        

If you have written Java or C # before, you will find that the blocks in Swift are try catch  somewhat different from theirs. In those languages, we would put the code that might throw the exception in a try, and Swift would put it in do and just add a try before the statement that could happen. In the way of Java or C #, in Swift we can know more clearly which call might throw an exception without stepping through the document.

Of course, Swift's abnormal mechanism is not perfect. The biggest problem is type safety, and without the help of documentation, we are now unable to directly know the type of exception thrown from the code. For example, in the above login  method, we do not know that we will be thrown when we look at the method definition LoginError  . An ideal exception API might look like this:

func login(user: String, password: String) throws LoginError

To a large extent, this is due to compromise with the previous NSError  compatibility, for the previous use of the NSError  API to express the error, we get the Error object itself is used like domain or error number of such attributes to differentiate and define, which with Swift The idea that the exception mechanism in 2.0 throws a direct use type to describe the error is temporarily incompatible. But there is reason to believe that with Swift's iterative update, the issue will be resolved in the near future.

Another limitation is that for non-synchronous APIs, throwing exceptions is not available-the exception is just a processing mechanism dedicated to synchronous methods. In the COCOA framework, when there is an error in the Async API, the original mechanism is preserved NSError  , such as the most commonly used NSURLSession  dataTask  APIs:

  func datataskwithurl ( _ url: Nsurl,:  ((!, nsurlresponse!,  nserror!)  -> void)  -> nsurlsessiondatatask   

For asynchronous APIs, although the exception mechanism cannot be used, because such APIs typically involve a network or time-consuming operation, the likelihood of errors is much higher, so developers cannot ignore such errors. But like the above API in fact, in our daily development often do not go directly to use, and will choose to do some encapsulation, in order to more easily invoke and maintenance. One of the more commonly used methods is the use of enum  . As an important feature of Swift, enum (enum) types can now be bound to other instances, we can also let the method return an enumeration type, then define the state of success and error in the enumeration, and associate the appropriate object with the enumeration value, respectively:

Enum Result { Case Success(String) Case Error(Nserror)}Func Dosomethingparam(Param:Anyobject) - Result { //... To do something, a successful result is placed in the success. IfSuccess{ Return Result.Success("Completed successfully") } Else { let error =  nserror (domain:  "Errordomain" , Code: 1, Userinfo:  nil)  return  result. Error (error)  }}             

When used, use let in switch to remove the results from the enumeration values:

LetResult=Dosomethingparam(Path)switch result { case< Span class= "PLN" > let . Success (ok let Serverresponse = Okcase let . Error (error let< Span class= "PLN" > Serverresponse = Error.               

In Swift 2.0, we can even specify generics in the enum, which results in a uniform result.

enum Result<T> { case Success(T) case Failure(NSError)}

We only need the type that is indicated when the result is returned , and we can use the same Result  enumeration to represent the different return results. Doing so reduces the complexity and possible state of the code, and does not gracefully address type-safety issues, which can be described as double benefit.

Therefore, in the Swift 2 era of error handling, the general best practice now is to use the exception mechanism for the synchronization API, using generic enumerations for asynchronous APIs.

Recommended reading:
  • Apple launches new programming language Swift
  • Swift functions (function declarations, function arguments, and types)
  • Swift type reference
  • Midstream College Swift language programming Training Video Tutorial Xcode6 basic use
  • Midstream College Swift language programming training video tutorial 17 optional data type forced extraction
  • Midstream College Swift language programming training video Tutorial 33 logical operators or non-detailed
  • 06 Dictionary-swift Language Quick Start Video tutorial
  • Swift Companion Script
  • Swift Mode Reference
  • Swift language Getting Started tutorial
  • Requestanimationframe Best Practices

Swift error and exception handling---South Peak sub

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.