How To Use Standard Result Type In Swift 5.0


Swift's current error-handling, using throws, try and catch, offers automatic synchronous handling of errors through explicit syntax and runtime behavior, However, it lacks the flexibility needed to cover all the propagation and handling in the language.
Swift 5.0 has finally introduced the new Result type to handle the result of the asynchronous function using an enum. There are only two cases that both use Swift Generic associated values,
  1.  Success with the value of a result.
  2.  Failure with the type that implements error protocol. If you want, you can use a specific error type, such as NetworkError or AuthenticationError, which allows us to have types throws for the first time in Swift.
The Result type really helps us to simplify handling the result of an asynchronous function as there are two cases, success, and failure.
Asynchronous APIs 
In this example, we are going to have only one possible error, which is that the requested URL string is not a valid URL.
  1. enum NetworkError: Error {  
  2.     case bad URL  
  3. }  
The fetching function will accept a URL string as its first parameters, and a completion handler second parameters. The completion handler will accept itself a Result where succuss case will store an integer, and failure case will be some sort of NetworkError.
  1. func fetchMessageCount(from urlString: String, completionHandler: @escaping (Result<Int, NetworkError>) -> Void)  {  
  2.     guard let url = URL(string: urlString) else {  
  3.         completionHandler(.failure(.badURL))  
  4.         return  
  5.     }  
  6.     // complicated networking code here   
  7.     print("Fetching \(url.absoluteString)...")  
  8.     completionHandler(.success(5))  
  9. }  
To use the above code we need to check value inside the Result to see whether your call is succeeded or failed like below,
  1. fetchMessageCount(from: "") { result in  
  2.     switch result {  
  3.     case .success(let count):  
  4.         print("\(count) unread messages.")  
  5.     case .failure(let error):  
  6.         print(error.localizedDescription)  
  7.     }  
  8. }  
Even in a simple scenario, Result has given us two benefits,
  1. The Error we get back is now strongly typed: it must be some sort of type NetworkError. the Swift regular throwing function is unchecked so can throw any type of error.
  2. It's now clear that we will get back either successful or an error - it is not possible to get both or neither of them. 


That's it, our API service looks pretty simple and clean with Result Type as the completion handler. There are many other feathers for Result Type such as a map and flatMap Result to another Result. Result type really simplifies the callback completion handler into success and failure cases.