cesarcarlos
cesarcarlos

Reputation: 1441

Using Alamofire to load images using URLs from JSON

I am building a Table View with remote data for an iOS app. I am using AlamoFire and SwiftyJSON to load a JSON file with a bunch of episodes.

The JSON file is structured like this:

{
  "id": "456",
  "name": "EpOne",
  "description": "Episode description 1",
  "imageURL": "http://myimage.com/myimagefile1.jpg"
},
{
  "id": "789",
  "name": "Eptwo",
  "description": "Episode description 2",
  "imageURL": "http://myimage.com/myimagefile2.jpg"
} ...

So I call

getEpisodes(url: endpoint)

from ViewDidLoad. This runs the following:

func getEpisodes(url: String) {
    Alamofire.request(url, method: .get).validate().responseJSON { response in
        switch response.result {
        case .success(let value):
            let json = JSON(value)
            self.buildEpisodeArray(json: json)

        case .failure(let error):
            print(error)
        }
    }
}

func buildEpisodeArray(json: JSON) {
    if let allEpisodes = json["episodes"].array {
        for singleEpisode in allEpisodes {
            let currentEpisode = Episode()
            currentEpisode.name = singleEpisode["name"].string!
            currentEpisode.imageURL = singleEpisode["imageURL"].string!
            episodes.append(currentEpisode)
        }
    }
    tableView.reloadData()
}

Then I load the data into my cells

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cellIdentifier = "Cell"
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! EpisodeCell
    cell.nameLabel.text = episodes[indexPath.row].name

    // TODO Get the image

    return cell
}

At this point everything works fine. The problem is when I try to load the images. I have checked a few tutorials (I'm kind of new at this) and after getting the data with Alamofire, they use contentsOf: url to get the images. So in my case, I would replace "// TODO Get the image" with

// Get the image
    if let url = NSURL(string: episodes[indexPath.row].imageURL),
        let data = NSData(contentsOf: url as URL) {
        cell.episodeImage.image = UIImage(data: data as Data)
    }

This loads the images but the table view is mega slow. But, doesn't using contentsOf: url go against the benefits of having loading the data with alamofire (I believe this is why the table is so slow when I scroll up and down)?

Shouldn't I be loading the images asynchronously? And if so, do I make a separate Alamofire.request for each image?

I have found tutorials to load data with Alamofire, and others to load images (but nothing else), but what if I want to load data and also load images to go with that data?

Thanks for any help you can provide.

Upvotes: 1

Views: 842

Answers (1)

AzrimZ
AzrimZ

Reputation: 277

I would suggest you, to use SDWebImage, it also handles image caching out of the box: https://github.com/rs/SDWebImage

It is very easy to use it basically:

import SDWebImage

// Get the image
cell.episodeImage.sd_setImage(with: URL(string: episodes[indexPath.row].imageURL))

Upvotes: 1

Related Questions