Victor Campos
Swift URLSession Tutorial: Making Your First Network Request | Background Image

Swift URLSession Tutorial: Making Your First Network Request

Photo by Pelly Benassi on Unsplash

A few days ago, I was working on my first project that involved fetching data from an external API for my app. Since this is a fundamental task in software development, I thought about writing this tutorial on how to make a simple network request using the URLSession object and maybe help someone in the future (probably myself). So, join me, and let's work together!

URLSession

URLSession is a powerful API provided by Swift for handling network tasks, such as fetching data for our app, downloading files, and uploading data and files to remote locations.

Let's use the project I mentioned as an example. We're building an app that'll show the latest Bitcoin prices in different currencies. To make it happen, we'll use the URLSession to grab the data from the CoinAPI following four simple steps:

Important

If you're not currently working on a project, you can create a playground blank file in Xcode to follow along with this tutorial. Just make sure you import the Foundation framework.

Setting Up

Step 1: Create a URL

The URL structure identifies the location of the resource we want to access. When creating an instance of this structure, you'll notice that the same method can be called with different parameters. In our case, we'll initialize it using only the string param.

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
 
}

Step 2: Create a URLSession

In the next step we create and configure a session for our network request.

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
}

There are three types of URL sessions that we can use:

Making GET Request

Step 3: Give URLSession a task

Now that we have our URLSession set up and ready to go, it's time to assign a task to it. URLSession supports three key types of tasks:

These are the most commonly used tasks. We also have WebSocket and Stream tasks, but they're used in more advanced scenarios, so for now, I won't talk about them.

Implementing a data task for our session:

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
 
  let task = session.dataTask(with: url) { (data, response, error) in
 
  }
}

Step 4: Start the task

The task we added to our session initially has a suspended state, which means that it's waiting for us to start it. We do this by calling its resume() method.

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
 
  let task = session.dataTask(with: url) { (data, response, error) in
 
  }
 
  task.resume()
}

And, once we've done starting the task, we're able to continue and handle the response.

Handling response

When we print the data returned from the dataTask() method, it won't be possible for us to see its content.

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
 
  let task = session.dataTask(with: url) { (data, response, error) in
    // data has an optional type: Data?
    // again, we use optional binding to unwrap it
    if let safeData = data {
      print("raw data: ", safeData)
      // raw data: 138 bytes
    }
  }
 
  task.resume()
}

Although we know the data is in JSON format (based on our API's documentation), that's not exactly what we got. So, what should we do?

Parsing data in JSON format

To fix this, we need to parse the data and turn it into an actual Swift object with properties and methods.

Create a Struct with the expected JSON properties

struct CoinData: Decodable {
  let rate: Double
  let asset_id_quote: String
}

Parse JSON with the native JSONDecoder

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
 
  let task = session.dataTask(with: url) { (data, response, error) in
    if let safeData = data {
      do {
        let decoder = JSONDecoder()
 
        let decodedData = try decoder.decode(
          CoinData.self, // reference the type object
          from: safeData
        )
      } catch {
        print(error)
      }
    }
  }
 
  task.resume()
}

Access properties from API JSON response

Now, if we try to access the decodedData constant, we'll be able to get the rate and asset_id_quote properties we extracted from the API JSON response.

let urlString =
  "https://rest.coinapi.io/v1/exchangerate/BTC/BRL?apikey=YOUR-API-KEY"
 
if let url = URL(string: urlString) {
  let session = URLSession(configuration: .default)
 
  let task = session.dataTask(with: url) { (data, response, error) in
    if let safeData = data {
      do {
        let decoder = JSONDecoder()
 
        let decodedData = try decoder.decode(
          CoinData.self, // reference the type object
          from: safeData
        )
 
        print(decodedData)
        // CoinData(
        //  rate: 140113.1208321098,
        //  asset_id_quote: "BRL"
        // )
      } catch {
        print(error)
      }
    }
  }
 
  task.resume()
}

Conclusion

And that's it! You've successfully completed your first network request. Congratulations! As a next step, I encourage you to read Apple's documentation and learn more about the subject. I've provided you with a lot of links, so have at it.

If you have any questions, please feel free to reach out to me on Twitter or Linkedin. Thank you very much for joining me. Great work, and see you next time! 🙋🏻‍♂️