Downloading images in Swift using PromiseKit and Alamofire
By: Dimitar Stefanovski
Tags: iOS, Promisekit, Swift, Asynchronous, Swift Programming

Problem

Networking code can get really messy if we have to download some content from a remote location.

Downloading set of 40 photos and representing it to a collection view

First we have to know the path (URL) from where we want to download the content (in our case that would be a photo). Second, probably that location or path will be written in some REST API endpoint request and after we process that JSON data response we have to start downloading the image and at last we have to update our UI.

All of this have to be done on a background thread because we do not want to block the main thread, and of course we want our app to stay responsive.

Best solution for this types of problems is using asynchronous programming and if we want our code to look very clean and tidy PromiseKit is the best choice. If you are new to asynchronous programming please check my previous post about How to use PromiseKit for Swift.

Next we’ll install PromiseKit and Alamofire library for networking requests using CocoaPods dependency manager. For installing the libraries with other dependency managers please visit the official documentation of PromiseKit https://github.com/mxcl/PromiseKit and Alamofire https://github.com/Alamofire/Alamofire.

Installing PromiseKit and Alamofire with CocoaPods

If you haven’t installed CocoaPods yet this is the time to do it. Go to the terminal app and write:

$ sudo gem install cocoapods

For details about using the CocoaPods dependency manager please visit official site https://cocoapods.org/.

Create new Xcode project (Single View Application) and in the directory of the project create new podfile using the command pod init .

Open the podfile and add the PromiseKit and Alamofire dependency libraries:

target 'YourProjectTarget' do

use dynamic frameworks

use_frameworks! pod 'PromiseKit'

pod 'Alamofire' end

Save the podfile and at this point you can install the libraries using the pod install command in the terminal:

$ pod install

From now you have to open the newly created workspace file .xcworkspace instead of .xcodeproj. That’s it, now we are ready using PromiseKit and Alamofire in our project.

Real world example

In this tutorial we’ll download set of photos from a remote location. The url’s of the photos we assume that will be written in some REST API endpoint and for the purpose of this example we’ll use placeholder API https://jsonplaceholder.typicode.com/photos that has url’s for 5000 photos. Downloading the photos can take some time so we’ll show a preloading animation with activityIndicator component and hide it when downloading has finished. We will not persist the photos, they will be stored in a temporary array [UIImage] . For displaying the photos i’m using UICollectionView but you are free to use any visual component for displaying.

Steps to take:

Show preloading animation Fetch and serialize json response Download photos Hide preloading animation and update the UI

The response form the API request is in the following JSON format:

[

{

"albumId": 1,

"id": 1,

"title": "accusamus beatae ad facilis cum similique qui sunt",

"url": "https://via.placeholder.com/600/92c952",

"thumbnailUrl": "https://via.placeholder.com/150/92c952"

},

{

"albumId": 1,

"id": 2,

"title": "reprehenderit est deserunt velit ipsam",

"url": "https://via.placeholder.com/600/771796",

"thumbnailUrl": "https://via.placeholder.com/150/771796"

},

...

]

With Alamofire and with a little help of the Codable protocol in Swift we’ll convert the json response in array of Photo objects. First let’s define the Model object (struct Photo ):

struct Photo: Codable {

let albumId: Int

let id: Int

let title: String

let url: String

let thumbnailUrl: String

}

If we write this code in one function, that will look like this:

How can we avoid the nesting of the code? How can we separate the concerns in different code blocks?