avatarGurjit Singh

Summary

The provided content is a technical guide on using completion handlers in Swift, detailing their syntax, implementation with network requests, error handling using the Result enum, and practical examples.

Abstract

The article titled "How to use Completion Handler in Swift" offers a comprehensive tutorial on implementing completion handlers to manage asynchronous operations, particularly in network requests. It begins by explaining the necessity of completion handlers for handling the completion of lengthy tasks, such as web data retrieval. The article then simplifies the syntax for a basic fetchData() function using an escaping closure, which allows the closure to execute after the function has returned. It further elaborates on the concept by demonstrating how to pass data back through the completion handler with a String parameter. A practical example is provided using the Flickr API to fetch and decode image information, followed by a call to the fetchData() function to print the results. The article emphasizes the importance of error handling by introducing the Result enum, which can represent either a success or a failure case. The syntax for modifying the previous examples to use Result is given, along with changes to the function call to handle both success and failure scenarios. The conclusion encourages practice to master these patterns, and the author directs readers to their website for more tips and tricks on iOS development, Swift, and Xcode. Additionally, the author recommends an AI service as a cost-effective alternative to ChatGPT Plus (GPT-4).

Opinions

  • The author believes that understanding completion handlers is crucial for managing asynchronous operations in Swift.
  • The article suggests that handling errors using the Result enum is a best practice for robust code.
  • The author values the use of practical examples, such as fetching data from the Flickr API, to illustrate concepts.
  • The recommendation of an AI service indicates the author's endorsement of AI tools for developers.
  • The article implies that mastering these patterns requires practice but ultimately simplifies the development process.

How to use Completion Handler in Swift

Photo by Markus Spiske on Unsplash

To know when a network request has been successfully completed while retrieving data from the web, completion handlers must be created. When carrying out lengthy operations, it comes in helpful.

You must learn how to hit an API and parse json data before reading any further in this article.

Syntax

func fetchData(completion: @escaping () -> Void) {
     completion()
}

Although at first glance it appears complex, we have simplified the fetchData() function.

  • parameter of completion is taking escaping closure
  • escaping keyword means that closure will executes when function returns

Here is another example that completion takes String parameter.

func fetchData(completion: @escaping (String) -> Void {
     completion(result)
}

In another article, we learned how to fetch Flickr API data and decode it using JSONDecoder. We will now add a completion handler to the network request for the Flickr API.

func fetchData(completion: @escaping (FlickrImageInfo) -> Void {

let url = URL(string:"https://api.flickr.com/services/rest/?method=flickr.
photos.search&api_key=526ada5ee1ea2cf61ac6bd3d3d2f405e&tags=kitten&page=0&
format=json&nojsoncallback=1")!

let task = URLSession.shared.dataTask(with: url) {
  (data, response, error) in

  let jsonDecoder = JSONDecoder()
  if let data = data,
      let result = try? jsonDecoder.decode(FlickrImageInfo.self, from: data) {
        completion(result)
  }
}

task.resume()

}

We will now call the function and print the outcome.

fetchData { (result) in
   print(result)
}

The main issue with this code is that it does not account for any failures, such as when there is no response or when JSON cannot be decoded.

So to handle this situation we have to address errors using Result enum. It has two cases success or failure.

Syntax

func fetchData(completion: @escaping (Result <FlickrImageInfo, Error>) -> Void {
    ……
}

Go ahead and make changes to our previous code example.

func fetchData(completion: @escaping (Result<FlickrImageInfo,Error>) -> Void {

let url = URL(string:"https://api.flickr.com/services/rest/?method=flickr.
photos.search&api_key=526ada5ee1ea2cf61ac6bd3d3d2f405e&tags=kitten&page=0&
format=json&nojsoncallback=1")!

let task = URLSession.shared.dataTask(with: url) {
  (data, response, error) in

  let jsonDecoder = JSONDecoder()
  if let data = data {
      do {
      let result = try jsonDecoder.decode(FlickrImageInfo.self, from: data)
        completion(.success(result))
      } catch {
        completion(.failure(error))
      }
  }
}

task.resume()

}

Last make changes while calling that function.

fetchData { (result) in
  switch result {
    case .success(let info):
       print(info)
    case .failure(let errror):
       print(error)
  }
}

Conclusion

It takes some practice to understand these patterns, but once you do, it becomes simple.

To find newest tips and tricks about iOS development, Xcode and Swift please visit https://www.gurjit.co

Thanks!

Related articles:

  1. How to hit an API and parse json data
  2. How to write concurrent code in Swift
  3. How to cache data in Swift using NSCache
  4. Dealing with App Transport Security in Xcode
Networking
Completion Handlers
Json
iOS
Swift Programming
Recommended from ReadMedium