Call Can Throw, but It Is Not Marked With 'try' and the Error Is Not Handled
                       The first time I saw error treatment on WWDC'due south Platform Country of the Union, I thought "here nosotros get again... exceptions". It quickly became clear that Swift'south error handling isn't the same as Objective-C exceptions. So what does this fault handling look like? Where are the differences? Permit'south dive into it! The first time I saw error handling on WWDC's Platform Land of the Union, I thought "here we go again... exceptions". It quickly became clear that Swift's error handling isn't the aforementioned as Objective-C exceptions. Actually, information technology introduces several improvements, in both performance and readability. So what does this error handling look like? Where are the differences? Allow's dive into it! Every bit you may expect, a few new keywords were introduced. Merely first of all, allow's take a look at this code: A uncomplicated division operation, where nosotros cheque if a divisor is not equal to 0, so we tin can safely obtain the consequence. Information technology's not the best implementation in Swift 2.0 and we can improve it with the               Let's modify our function and and then explain it: What changed here is that               Going dorsum to our function - in that location's however room for comeback. Stopping app execution for an incorrect divisor is not the best solution. We would prefer to somehow handle the trouble, rather than just crash the app. There are a few new things in Swift 2.0 that will assist united states here. The beginning is               Swell! At present we want to get this error out of our function when an incorrect divisor is given, and nosotros tin can exercise this with the                              To do this we only add               Now the compiler seems to be much happier.               If               Now another problem appears - the compiler kindly reminds us that calling               Did you discover how nicely the compiler informed us that the role we desire to telephone call can neglect? I call up information technology'due south great! Nosotros're getting closer, but even so nosotros're not handling this error inside the function. I call back this is not the best place to handle errors, then what we want to do is to rethrow information technology along to the caller. Swift ii.0 has another keyword for that -               We used               Permit's become dorsum to the previous instance and try to telephone call our               We know how to call a throwing function, simply what near getting the error if something goes wrong? We will make use of a               Information technology's worth mentioning that               I believe we've covered everything most error handling in Swift 2.0. The but matter remaining is the divergence between the error handling feature and regular exceptions. Swift errors are different to Objective-C exceptions for several reasons. The first 1 is that error handling in Swift is not as fell as exceptions. When an exception is triggered the stack is unwinded immediately, which may lead to memory leaks. With Swift, there's no such thing, because it just exits the scope. In that location's besides a performance price with Objective-C exceptions since they're existence resolved at runtime, while the Swift compiler can optimize our code. The entire mechanism also improves readability with syntactic carbohydrate similar               Swift also requires y'all to catch all thrown errors. The situation of an unhandled fault will never occur, which is the main deviation when comparing to exceptions. Error handling is definitely a stride forward. We tin check preconditions in our function implementation. We tin can return a meaningful error and handle it gracefully. It's definitely better than Objective-C error handling pattern with passing               Well done, Apple!               Are you getting started with Swift? We bring y'all an open source style guide created by our iOS team, cheque it out!             
            Basics
                                              
                                                                                                                  func                      divide(                        dividend                      :                      Bladder,                      by                      divisor:                      Float)                      ->                      Float                      {                                                                                                                         if                      divisor                      ==                      0.0                      {                                                                                                                         fatalError(                        "Division by naught is not immune"                      )                                                                                                   }                                                                                                                         return                      dividend                      /                      divisor                                                                                                               }                   guard              argument.Guards
                                              
                                                                                                                  func                      split(                        dividend                      :                      Float,                      by                      divisor:                      Float)                      ->                      Float                      {                                                                                                                         guard                      divisor                      !=                      0.0                      else                      {                                                                                                                         fatalError(                        "Partition by nil is non allowed"                      )                                                                                                   }                                                                                                                         render                      dividend                      /                      divisor                                                                                                               }                   guard              ensures that the divisor will be dissimilar to 0.0, otherwise it immediately prints an mistake message and stops execution. It besides allow u.s.a. know, further in the function implementation, that the divisor volition always be correct. This office is pretty simple, if not a bit likewise uncomplicated, just by and large              baby-sit              helps understanding when the function will exit with failure. Is              guard              different in any way to a simple              if              statement? Aye, a bit. Yous can apply              guard              forth with              let              and              where              to unwrap optionals and check conditions. The significant differences are that dissimilar              if              statements,              baby-sit              unwraps optionals outside of its scope and also that it runs but if conditions are not met, which means it works similarly to exclamation (merely without crashing an app). Call up nigh              guard              as a              let-else              handler rather than an              if              statement.ErrorType
            ErrorType. It'due south a protocol that is used in the mistake handling machinery. Only errors conforming to information technology tin be thrown.              ErrorType              also allows bridging to              NSError              - cool! Let's make our own division error so:                                  
                                                                                                                  enum                      DivisionError:                                              ErrorType                      {                                                                                                                         case                      ByZero                                                                                                                                   }                   Throw
            throw              keyword:                                  
                                                                                                                  func                      divide(                        dividend                      :                      Float,                      past                      divisor:                      Bladder)                      ->                      Float                      {                                                                                                                         guard                      divisor                      !=                      0.0                      else                      {                                                                                                                         throw                      DivisionError.ByZero                                                                                                                       }                                                                                                                         return                      dividend/divisor                                                                                                               }                   throw              lets us literally throw an fault out of the function. But wait - the compiler complains hither that the error is not handled and it also talks about some              throws. Nosotros're already throwing, what's wrong? How can we handle this fault? Well it's truthful that we don't handle this error, but we don't desire to right now. We want to laissez passer this responsibility to the user of our convenient function.Throws
            throws              earlier the return type in the function's declaration:                                  
                                                                                                                  func                      separate(                        dividend                      :                      Float,                      by                      divisor:                      Float)                      throws                      ->                      Float                      {                                                                                                                         guard                      divisor                      !=                      0.0                      else                      {                                                                                                                         throw                      DivisionError.ByZero                                                                                                                       }                                                                                                                         return                      dividend                      /                      divisor                                                                                                               }                   throws              marks our part as a throwing one. Actually, our role at present has a different type. If we endeavour to assign              divide(_:, by:)              to the variable of type              (Float, Bladder) -> Float              the compiler will protest. The correct type is              (Float, Float) throws -> Float. However, you tin can still assign a non-throwing function/closure to the throwing type, which means that throwing types are supertypes of their non-throwing versions. Confused? Take a await at an example:                                  
                                                                                                                  func                      throwingOperation()                      throws                      ->                      Int                      {}                                                                                                                         func                      nonThrowingOperation()                      ->                      Int                      {}                                                                                                                                                                                                                                                                                                                                                                       func                      performOperation(                        operation                      : ()                      ->                      Int)                      ->                      Int                      {                                                                                                                         render                      performance()                                                                                                   }                                                                                                                                                                                                                                                                                                                                                                       performOperation(throwingOperation)                                              //                        incorrect - Invalid conversion from throwing function ... to not-throwing ...                                                                                                                                                                               performOperation(nonThrowingOperation)                                              //                        right                                       performOperation(_:)              would take a throwing type as an argument both calls would exist correct.                                  
                                                                                                                  func                      performOperation(                        operation                      : ()                      throws                      ->                      Int)                      ->                      Int                      {                                                                                                                         return                      functioning()                                                                                                   }                                                                                                                                                                                                                                                performOperation(throwingOperation)                                              //                        correct                                                                                                                                                                               performOperation(nonThrowingOperation)                                              //                        correct                                       Effort
            performance()              "can throw, only it is not marked with              try              and the error is not handled". Permit'southward mark it with              attempt              then:                                  
                                                                                                                  func                      performOperation(                        operation                      : ()                      throws                      ->                      Int)                      ->                      Int                      {                                                                                                                         return                      try                      performance()                                                                                                               }                   Rethrows
            rethrows. This is what it looks like with              rethrows:                                  
                                                                                                                  func                      performOperation(                        performance                      : ()                      throws                      ->                      Int)                      rethrows                      ->                      Int                      {                                                                                                                         return                      try                      functioning()                                                                                                               }                   rethrows              in the same way every bit              throws, but it's a bit dissimilar, because the Swift compiler treats it as a office attribute rather than a type. Information technology behaves a flake like an optional              throws, so we can switch smoothly from a throwing to non-throwing function, based on the context this function is used in.divide(_: by:)              function:Do - catch
            do-catch              statement:                                  
                                                                                                                  do                      {                                                                                                                         try                      split(4,                      past:                      0)                                                                                                   }                      grab                      DivisionError.ByZero                      {                                                                                                                         print(                        "Division by nix is not allowed"                      )                                                                                                               }                   practice              can have any statements yous like, including multiple              try              calls. Also at that place can be multiple              grab              statements that will blueprint-lucifer different errors, and then you lot don't need to write nested              practise-catches.Swift errors are not exceptions
            attempt              and              throws/rethrows              keywords. This helps developers to piece of work with code and is merely easier to read and understand.Summary
            NSError*              to methods, not to mention the exceptions mechanism, which we are being discouraged to use. On top of that, Swift'southward type organisation helps us writing all the lawmaking.
Source: https://www.netguru.com/blog/error-handling-swift
0 Response to "Call Can Throw, but It Is Not Marked With 'try' and the Error Is Not Handled"
Postar um comentário