Swift REST API call using Alamofire

Lucky Mehndiratta
4 min readJul 23, 2022

Here we are going to get the data from the backend using REST API by Alamofire library. Whenever we are going to convert our dummy data models into dynamic data models then we need to get data from the backend server. There are multiple ways to get the data or connect the iOS app with the backend. But, Today we will use the REST API method to get the data from the server
First needs to add the pod into the pod file(If you're going to use the pod the first time, First setup the pods for your project then you can add this pod into your pod file)
pod ‘Alamofire’ — — — -> Add this pod to your pod file and save it then run the command pod install
If your pod is successfully added then just copy the following code and paste it into the files of your project

First, you need an API URL, on which you are going to get the data from the backend
enum URLs:CustomStringConvertible{
//MARK: Define the cases of your API endpoints for your project
case
getLocalInfo

//MARK: Complete the Path of your API
var
path: String{
switch self {
case .getLocalInfo:
return baseURL + apiVersion + “endpoints for this API”
}
}

var description: String{
return self.path
}

//MARK: Base URL for your Backend server based on the environment like as development, QA, and production
var
baseURL:String{
return “your base URL for the API calling”
}

//MARK: Version of your API(you can remove this too if there is no API version in your project or add other things based on your server API)
var
apiVersion: String{
return “your apiVersion for the API calling”
}
}

Second and Third you need the Response Object and Request Parameter

open class ResponseObject {
// This is the network status code
fileprivate var networkStatusCode: Int

// Status code in the response (in json “{“code”:309, etc. etc.}”
fileprivate var apiStatusCode: Int

// Message to be displayed to the user, shouldn’t be used since we’ll map error codes to the user messages
fileprivate var message: String

// Status success/failure
fileprivate var apiStatus: String

// Debug message for developer
fileprivate var debugMessage: String

// Data of type T in the response
fileprivate var data: AnyObject

public init(networkStatusCode: Int, apiStatusCode: Int, message: String, apiStatus: String, debugMessage: String, data: AnyObject) {

self.networkStatusCode = networkStatusCode
self.apiStatusCode = apiStatusCode
self.message = message
self.apiStatus = apiStatus
self.debugMessage = debugMessage
self.data = data
}
}

import Alamofire
open class RequestParameter {
var url: String

/// Method type e.g. GET/POST etc.
var method: Alamofire.HTTPMethod

/// Headers needed for the api call
var headers: [String: String]?

/// Url encoded parameters
var parameters: [String: Any]?

var isShowPopUp:Bool?
var viewController:UIViewController?
fileprivate init(url: String, method: Alamofire.HTTPMethod, headers: [String: String]? = nil, parameters: [String: Any]? = nil,isShowPopUp:Bool,viewController:UIViewController?) {

self.url = URL
self.method = method
self.headers = headers
self.parameters = parameters
self.isShowPopUp = isShowPopUp
self.viewController = viewController
}
public static func createRequestParameter(_ url: String, method: Alamofire.HTTPMethod, headers: [String: String]? = nil, parameters: [String: Any]? = nil,isShowPopUp:Bool,viewController:UIViewController?) -> RequestParameter {

return RequestParameter(url: url, method: method, headers: headers, parameters: parameters,isShowPopUp: isShowPopUp,viewController: viewController)

}
}

Check Network before hitting the API, Whether an Internet connection is there or not

import Foundation
import SystemConfiguration

public class Reachability {
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
let ret = (isReachable && !needsConnection)
return ret
}
}

Now, Make an API request

import Foundation
import Alamofire

public typealias SuccessClosure = (_ data: Data?) -> (Void)
public typealias FailureClosure = (_ error: Error?, _ data: Data?, _ statusCode: Int?) -> (Void)

class NetworkManagerWrapper: NSObject {

static func makeRequest(_ requestParamter: RequestParameter, encoding: ParameterEncoding = JSONEncoding.default, success: @escaping SuccessClosure, failure: @escaping FailureClosure) {

if Reachability.isConnectedToNetwork(){
print(“Internet Connection Available!”)

let request = AF.request(requestParamter.url,method:requestParamter.method, parameters: requestParamter.parameters, encoding: encoding, headers: HTTPHeaders(requestParamter.headers ?? [“”:””])){ $0.timeoutInterval = 60 }

if(requestParamter.isShowPopUp!){
//Show Loader here as per your project requirement
}

request.responseData{ (dataResponse) in
print(dataResponse.response?.statusCode as Any)
if(requestParamter.isShowPopUp!){
//Hide your loader here
}

print(dataResponse)
#if DEBUG
if let data = dataResponse.value {
let responseString = String(data: data, encoding: .utf8)
if responseString != nil {
// debugPrint(“Response string:\(responseString!)”)
}
else {
// debugPrint(“Response string is null”)
}
}
#endif
if let error = dataResponse.error {
failure(error, dataResponse.value, nil)
}
else if dataResponse.response?.statusCode == 200 || dataResponse.response?.statusCode == 201 {
success(dataResponse.value)
} else {
failure(nil, dataResponse.value, dataResponse.response?.statusCode)
}
}
}
else{
print(“Internet Connection not Available!”)
}
}
}

API Call

@discardableResult
public static func getLocalInfo(_ isShowPopUp:Bool,_ viewController:UIViewController,success: @escaping SuccessClosure, failure: @escaping FailureClosure) -> Request{

let token = “Add your API Token here if your API needs to pass token in your API call else remove this and Authorization from the header(Key and value both)”

let headers = [“Authorization”: “Bearer \(token)”,”Accept”: “application/json”]
let requestParameter = RequestParameter.createRequestParameter(URLs.getLocalInfo.path, method: .get, headers: headers, parameters: nil,isShowPopUp:isShowPopUp,viewController:viewController)

return NetworkManagerWrapper.makeRequest(requestParameter, success: success, failure: failure)
}

Call above method in your view model, controller based on your choice and get the data from the API. After that, you need to parse that data based on your choice and create a model of that for further use.

Note: If you want to see the result just replace the following
return baseURL + apiVersion + “endpoints for this API”
with
return “http://ip-api.com/json/"
and add this into your info.plist(Why? because the above-mentioned API is HTTP that why do we need to add this key into our info.plist API, else there is no need to add this.)
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

Happy Coding!!

--

--