Alamofire

Alamofire:

Alamofire is a HTTP networking based library for iOS and macOS. It is used to handle HTTP request and response. It is the wrapper class of URLSession.

Before Alamofire:

  1. You need to prepare all request by yourself
  2. Task handling is complicated
  3. Multipart request and File downloading & uploading is complicated
  4. Image caching needs to done by yourself

Uses of Alamofire:

  1. It’s incredibly easy to use and makes everything look a lot cleaner
  2. Task handling is easy.
  3. You can access data on the Internet with very little effort
  4. Upload files or data with multipart, stream easily.
  5. Download a file or resume a download already in progress.
  6. You can use AlamofireImage to download and cache images

Work with Alamofire:

Alamofire library provides you an easy way to handle all network related task. It reduces the efforts of developer because developer need not to directly deal with` URLSession `. Alamofire uses ` URLSession ` internally. Alamofire calls for a similar approach in that, one creates a router by conforming to a protocol, URLRequestConvertible. Under the hood, Alamofire calls for a singleton pattern that’s built on top of an URLSessionConfiguration. Everything with Alamofire is asynchronous.

1. Data Request with and without Alamofire:

Here is the code to send request with ` URLSession `:

// Create object of URLSessionConfiguration
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 40

// Create object of URLSession
let session = URLSession(configuration: sessionConfig)

// Prepare request
let url = URL(string: "www.example.com")
var request = URLRequest(url: url!)
let newDict = ["Your key": "Your value"]
request.httpMethod = "POST"
do {

    // Convert request to json
    let jsonData = try JSONSerialization.data(withJSONObject: newDict, options: [])
    request.httpBody = jsonData
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")

    // Prepare task
    let task = session.dataTask(with: request, completionHandler: {
        responseData, response, error -> Void in

        // Handle response
        print(response!)
        do {
            if responseData != nil {
                let json = try JSONSerialization.jsonObject(with: responseData!, options: .mutableLeaves)
                // Use response json
            } else {
                // Handle null data here
            }
        } catch {
            // Handle your exception here
        }
    })

    // Send request
    task.resume()
} catch {
    // Handle your exception here
}
  1. Create an object of `URLSessionConfiguration` for session Configuration.
  2. Create object of session class using ` URLSessionConfiguration ` object.
  3. Prepare URLRequest object using your url and set request type in ` httpMethod `.
  4. Convert Dictionary to JSON using ` JSONSerialization.data() ` and add it in request body and add other parameters for request header.
  5. Make an object of task using ` session.dataTask(with: request, comletionHandler: nil) `
  6. Now resume the task to start execution.
  7. In completion handler, you receive the response. Do whatever you want to do with this data 🙂

If you use alamofire then you need not to do all the steps. You just need to follow few of them.

// Create object of URLSessionConfiguration
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForResource = 40 // seconds

// Create object of SessionManager
let manager = Alamofire.SessionManager(configuration: sessionConfig)
let url = URL(string: "www.example.com")

// Send Request
manager.request(url!, method: HTTPMethod.post, parameters: ["your key": "value"], encoding: JSONEncoding.default, headers: nil).responseData(completionHandler: { response -> Void in

    // Handle response
    if response.result.isSuccess {
        print(response.result.value!)
        // Perform your task here
    } else {
        // Handle error
    }
})
  1. Create URLSessionConfiguration object and set it’s other properties
  2. Create object of SessionManager using  URLSessionConfiguration object. It internally use URLSession.
  3. Prepare request using request method of SessionManager. You need to pass url, http method type, request body, encoding and header. It internally creates object of URLRequest and make an task and add it in request queue.
    Here responseData have a completion handler. If request is completed and response is received then it calls the completion handler and remove that request from request queue.
  4. Check if data is received successfully. If yes, then do anything with your data.

2. File Uploading with and without Alamofire:

File uploading with only URLSession is little bit complicated. In this you need to prepare multipart request by yourself.

let imageArray = [UIImage]()
let boundry = "**********"
var request = URLRequest(url: URL(string: "http://api.imagga.com/v1/content")!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 40)
request.httpMethod = "POST"
request.addValue("multipart/form-data; boundary=\(boundry)", forHTTPHeaderField: "Content-type")

// Add Extra Parameters
var dataForm = Data()
dataForm.append("\r\n--\(boundry)\r\n".data(using: .utf8)!)
dataForm.append("Content-Disposition: form-data; name=\"param1\";\r\n\r\n10001".data(using: .utf8)!)

// Adding Images in multipart request
if imageArray.count > 0 {
   for image in imageArray {
      let timestamp = Date().timeIntervalSince1970*1000
      let data = UIImageJPEGRepresentation(image, 0.6)
      dataForm.append("\r\n--\(boundry)\r\n".data(using: .utf8)!)
      dataForm.append("Content-Disposition: form-data; name=\"fileToUpload[]\"; filename=\"\(timestamp).jpg\"\r\n".data(using: .utf8)!)
      dataForm.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
      dataForm.append(data!)
   }
}
dataForm.append("\r\n--\(boundry)--\r\n".data(using: .utf8)!)

// Create session and send multipart request
let urlSession = URLSession(configuration: URLSessionConfiguration.default)
request.httpBody = dataForm
let uploadTask = urlSession.dataTask(with: request, completionHandler: { data, response, error in

   let output = String(data: data!, encoding: .utf8)
   print(output)
   if error == nil {
      DispatchQueue.main.async {
         //Upload successful
      }
   } else {
      DispatchQueue.main.async {
         //Upload failled
      }
   }
})

// Upload request
uploadTask.resume()
urlSession.finishTasksAndInvalidate()
  1. Make request object with caching policy and timeout. Define its http method.
  2. Add Content-type in request body.
  3. Create data object for request body and add content boundary and other parameters.
    Now Convert image into data and append boundary, content-type, file name, and file data in data object. Repeat it for all images or files. Append boundary in last.
  4. Create ` URLSession ` object to send request.
  5. Add data in request body.
  6. Create task and start task execution.
  7. In completion handler of data task you get data, response and error. You can work anything with it.

In the given code, you can not get progress for uploading.
If you want to send a single file then you can use uploadTask of URLSession. But through this you can not send multiple files in single request. To send a single file you need to call given method:
`urlSession.uploadTask(with: request, from: dataForm)`
This method only send request and not let you if file is uploaded successfully. For that you need to implement `
URLSessionDataDelegate` methods to know the response and progress of  your request.

File uploading with alamofire is very easy. Here you need not maintain any queue for task.

// convert image to data object
guard let imageData = UIImageJPEGRepresentation(image, 0.5) else {
   print("Could not get JPEG representation of UIImage")
   return
}

// send multipart request
Alamofire.upload( multipartFormData: { multipartFormData in
   multipartFormData.append(imageData, withName: "imagefile", fileName: "image.jpg", mimeType: "image/jpeg")},

      to: "http://api.imagga.com/v1/content",
      headers: ["Authorization": "Basic xxx"],
      encodingCompletion: { encodingResult in

         // check the response
         switch encodingResult {
         case .success(let upload, _, _):
            upload.uploadProgress { progress in
               // Show progress
            }
            upload.responseJSON { response in
               // Handle response
            }
         case .failure(let encodingError):
               print(encodingError)
               // Handle Error
      }
   })
}

To upload the file you need to follow some easy steps:

  1. Convert your image or file in Data
  2. Call ` Alamofire.upload() ` method to upload data in multipart request. It appends your data and related information in multipartFormData and take url of server where you want to upload and header as argument. It maintains queue and send multipart request.
  3. In enclosingCompletion Handler, we receive result which tells whether it is success or failure. In success blog we can check the upload status.

3. File Downloading with and without Alamofire:

File downloading without Alamofire is a complicated task. Please have a look down:

func downloadFile() {
   let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
   let downloadRequest = urlSession.downloadTask(with: URL(string: "http://wallpaper-gallery.net/images/image/image-17.png")!)
   downloadRequest.resume()
}
    
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
   // Handle error while downloading
}
    
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
   let fileManager = FileManager.default
   let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
   let destURL = urls.first?.appendingPathComponent("test").appendingPathExtension("pdf")
   let downloadedData = try? Data(contentsOf: location)
   let _ = try? downloadedData?.write(to: destURL!)
   // File has been downloaded. Do extra work here if you want.
}
    
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
   // show progress
}

By Only URLSession you first create session configuration and then downloadTask with url and pass self as delegate. To get progress you need to confirm protocol ` URLSessionDownloadDelegate ` and implement given three methods to get response success, error or progress.

Using alamofire it become easy to download any file.

let url = URL(string: "http://wallpaper-gallery.net/images/image/image-17.png")

// Send download request
Alamofire.download(url!).response { (response) in
   // Handle response
   print("File: \(response.temporaryURL ?? "")")
}.downloadProgress { (progress) in
   let progress = progress.fractionCompleted * 100
   print(progress)
   // Show progress
}

 

4. Image Downloading and caching:

For downloading and caching you can use AlamofireImage pod. Using this library you do not need to cache by yourself. This library will download and cache your images.

For that you need to add AlamofireImage in your pod file and install it.
Now import it in your project.
Create an object of  ` ImageDownloader ` add pass the given parameters:

let imageDownloader = ImageDownloader(
  configuration: ImageDownloader.defaultURLSessionConfiguration(),
  downloadPrioritization: .fifo,
  maximumActiveDownloads: 4,
  imageCache: AutoPurgingImageCache(
    memoryCapacity: 2_000_000, // Memory in bytes
    preferredMemoryUsageAfterPurge: 1_000_000
  )
)

Here you can pass download priority i.e. fifo or .lifo as you want, maximum concurrent downloads and object of AutoPurgingImageCaching which take caching memory capacity as argument.

Now you can use that object of ImageDownloader to download image.

imageDownloader.download(urlRequest) { response in
  var img = UIImage()
  if response.result.value != nil {
    img = response.result.value!
  }
}

This method first check your image in cache. If it exist then return the image else it download the image, add it in cache and return it.

You can compare both the code and decide which one you want to use.

Steps to use Alamofire in your project:

  1. Import Alamofire:
    1. Add pod file using ` pod init ` command in terminal.
    2. Open pod file in editor and add given line in it:
    `pod ‘Alamofire’`  to add Alamofire library
    or
    ` pod ‘AlamofireImage’ ` for image downloading and caching.
    3. Open terminal add run command ` pod install ` to install library.
    This will add the latest version of Alamofire library in your project. Now you can use it.
  2. Use Alamofire in your project:
    When alamofire is installed in your project, so you can import it in your class where you prepare and send request. The way to use this Library is given above. Enjoy you request and response data with alamofire. 🙂

For more information please visit:

https://github.com/Alamofire/Alamofire

Leave a Reply