2️⃣GET Requests
Fall 2023 | Vin Bui
In this section, we will be using Alamofire and callbacks to perform network requests, specifically GET requests.
Creating a NetworkManager Class
It is common in iOS development to create a class that represents our backend calls. Let’s create this class and name it NetworkManager
. Make sure to import Alamofire.
We create this static variable called shared
that holds a singleton and make the initializer private
. This guarantees that only one instance of this class is created. To access this variable, we can simply use NetworkManager.shared
Creating a GET Request
Inside of this NetworkManager
class, we write functions to be called by our application. These functions will use Alamofire to send HTTP requests.
Assume there is a struct called Member
that represents an AppDev member.
We can write the following code to fetch the AppDev roster.
Let’s break down this code.
Create a function called
fetchRoster
that takes in a callback (completion handler) as an argument. This callback takes in an array ofMember
objects.Specify the endpoint which is the URL that we will call to fetch the data. We can test this with Postman.
Create a decoder to decode the data. If our object contains a
Date
property, then we need to specify the date decoding strategy. If the JSON contains fields with snake_case, then we also need to specify the key decoding strategy.Create the request using Alamofire.
Pass in the endpoint and specify the method (
.get
for GET,.post
for POST, etc).Validate the request to ensure that the status code is 2xx and if the content type matches.
Decode the response to
[Member]
using the decoder we created in Step 3.
Perform a switch statement on the response’s result.
If successful, pass to the callback the decoded response. A print statement is optional but recommended.
If failed, print an error statement about the error.
Note that we do not have to create the decoder inside of the function call. We can create a JSONDecoder
object and store it as a property in our NetworkManager
class to be used for all functions. The same can be applied to the endpoint variable containing a String value of our endpoint.
Calling the Network Request
There is a problem with this code that will be discussed in the next section below.
We call the function that we just created inside of the NetworkManager
class. Remember to use NetworkManager.shared
. To access the value passed into the callback, we simply use the in
keyword. For example, earlier we passed in an array of Member
objects to the callback. In this case, fetchedMembers
is holding the value that was passed in. We can call the variable whatever we want but it is very helpful to make it representative of the data.
Then, we do whatever we want with the data that we just fetched. If we are referencing a property outside of this function call, we will need to use self
.
Next, if we need to perform any UI updates such as updating a collection view, we put that in a DispatchQueue.main.async
block. This runs any code inside of the block on the main queue asynchronously. This is an advanced topic but the reason for this is so that the UI does not freeze while we are sending a network request.
Using weak self
weak self
Although the above code works, there is one major issue: we are retaining a strong reference to self
inside of a closure which can cause retain cycles (causing memory leaks). To go around this, we will retain a weak reference to self inside of the closure and then unwrap a strong reference. We do this by adding [weak self]
in our closure and using a guard let
to unwrap a strong reference.
You may have noticed that we also use weak
when creating our delegate properties. This is an advanced topic that we will discuss later, but for now, make sure to use weak self
every time we need to use self
in our networking calls.
Last updated