Power up your apps, use URLSession to use APIs in Swift
Tags: swift, api, urlsession, programming
Published: 2023-02-15 20:01:10

## Introduction

APIs or Application Programming Interface, lets the developers to access data given by an external server. Almost every single app that we use in our daily life uses APIs; Instagram for example, it doesn't have the data of their users in the local storage of your devices, that data is in an external server and it gets retrieved by the developer when needed. An API makes us able to create so great apps, for example, we can create an image generator powered by dall-e using their API or we can create a books app and integrate the Google Books API to power up the user experience but, to be able to do that, you have to know how to do it and that's exactly what I am going to explain, how to use URLSession in Swift.
Actually, there are two ways to use APIs in Swift, the third party way, which is basically using a library called AlamoFire, adding it to your project with CocoaPods or the Swift Package Manager (SPM) and the official way which is using URLSession which is already integrated in Swift so you don't have to add libraries or something similar and honestly, that's the way I prefer. So, let's start learning how to use URLSession.

## Interesting links
[Google Books API documentation](https://developers.google.com/books/docs/v1/getting_started)
[Status codes by Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
[URLSession official Apple Documentation](https://developer.apple.com/documentation/foundation/urlsession)


## Setting up a URLSession
First of all, you have to setup a URLSession, this is quite simple, just create a new constant called urlSession or anything else and access the singleton of URLSession
`let urlSession = URLSession.shared`

## Set the url
Now, you need to set the url that you want, of course this has to be the url you want to make the request to, here, you have two ways to do it.

### Way 1: Fixed url
In the case that you want to set a fixed url, and don't let the user to change anything to that url, meaning that, all the requests will be done to the same url, just create a constant and assign it the url as a string:
`let address = "https://pokeapi.co/api/v2/pokemon/1/"`

### Way 2: Letting the user customise the url
If you want to make the user able to customise the url, changing different information and making another requests this is the way that you should follow. In this case you have to use something called URLComponents, this allows you to build the url from scratch setting manually everything, the host, the path, query...
First, we have to create an instance of URLComponents:
`var urlComponents = URLComponents()`
Now, you can proceed to build your url by setting every component of it.
- The first thing is the protocol, access to the scheme property of URLComponents and assign it to the protocol that the url uses: (In the following example, the protocol used is https)

`urlComponents.scheme = "https"`
- Now you have to set the host of the url: (In this case : www.googleapis.com)

`urlComponents.host = "www.googleapis.com"`
- Once you've done this, its time to assign the path of the url, this is basically all the content between /: (In this case /books/v1/volumes)

`urlComponents.path = "/books/v1/volumes"`
- Now, you have to set the query items, that means all the items that are customisable from the url, like the search or the api key, if you have more than one query item, you can access the property .queryItems, that will create and array with all the queries that you need, otherwise, if you have only one item, just access to the property .query: (In this example, we have two query items, q and key)

```
urlComponents.queryItems = [
    URLQueryItems(name: "q", value: search)
    URLQueryItems(name: "key", value: key)
]
```
Ok, lets explain that code, specifically, the URLQueryItems, well, it gets two parameters, name and value, the name its just, as its name specifies, the name of the query, in this case q and key, you can know the name of the query by looking on the documentation of the API that you want to use, and the value, its just the string, int or any other data that will be assigned to that query, in this case, we should create a variable called search and that variable will contain a string with the search that you want to make. The other query, key, is not necessary in every API, just in some of them, in this case is necessary so if you want to make this exact example, you will have to go to the Google Apis documentation and claim your API key there, of course, its completely free. This is how the whole code should look:

```
let search = "Harry potter"
let key = "Here you have to place your API key"

urlComponents.queryItems = [
    URLQueryItems(name: "q", value: search)
    URLQueryItems(name: "key", value: key)
]
```

Now, you have endless possibilities, you can make the user enter whatever he wants, you can create a TextField with a @State variable and pass that variable to the search and many other things, here, the limit is your imagination.

Coming back to queryItems, once they are placed, you just need to build the url by accessing to the .url property of URLComponents and saving it into a new constant:

`let url = urlComponents.url`

Now, before we start creating the request we have to make a final thing, force the unwrap of the url and if it finds a nil value, it will throw an error. We will do this using guard:

```
guard let url = url else {
    throw NSError()
}
```

## Creating the request
First of all, we create the request using URLRequest:
`let request = URLRequest(url: url)`
Now, we have to say to the URLSession that we want to create a request, we have to do this by creating a dataTask:

```
let task = urlSession.dataTask(with: url) { data, response, error in
    if let data = data, let responseString = String(data: data, encoding: .utf8) {
        print(responseString)
    }
}
task.resume()
```

This can look a little bit tricky so let me explain you, first of all, you access the dataTask property of URLSession to create the request, dataTask requires an argument of type url, you have to pass it the constant url that comes from URLComponents, after that, we have a trailing closure with three variables, data (This will display us the size of the data requested), response (Response will display us the status code of the request plus the headers of the request in a json, if you don't know the meaning of the status code, I highly recommend you going into this page: [Status Codes by Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)), and error (This will only give us data when an error appears, this will display information about the error, in the case that the request is successful, the value of error will be nil). After that, we have to decode the data given using an if let sentence, so we create a new variable called responseString and we assign it a String with two values, data and encoding, data will be the data parameter of the trailing closure and encoding will be .utf8 and finally, inside the curly braces, we have to put the code that we want to execute if everything goes ok, in this simple case, we will print the results (They will be printed as a json file). In this way, you've made a request to an external url to retrieve information from their server, but only with this you will not be able to use the information given in your app, for that you have to parse that json file received using JSONDecoder but that, is for another article. Also, and before I close this, you may have been notice that there is a final sentence that says:
`task.resume()`
This is because all the tasks that have just been initialised, begin in a suspended status, the .resume() property just starts the method, this is quite important as if you miss it, the task will never get executed.

I hope you've enjoyed the article and you learnt how to use URLSession, soon I will release the part 2 of this article, showing how to parse the JSON file received by the server to be able to use it in your apps. See you then.