tommyd456
tommyd456

Reputation: 10703

Retrieve and display multiple images from URL

Experimenting with Swift3, Alamofire and AlamofireImage. I am trying to display some Instagram images in a tableview. I have a data.json file of Places retrieved using Alamofire which look like this:

{
  "places" : [
    { "name" : "place1", "url" : "http://instagramImage1.jpg" },
    { "name" : "place2", "url" : "http://instagramImage2.jpg" },
    { "name" : "place3", "url" : "http://instagramImage3.jpg" },
  ]
}

I have setup PlaceTableViewCell with a UIImageView and attached it to an outlet in the corresponding controller.

I also have a PlaceTableViewController which includes:

var places = [Place]() //empty array to store places

In viewDidLoad() method I call a private function:

loadJson()

and the function looks like this:

private func loadJson() {
    Alamofire.request("https://example.com/data.json").responseJSON { response in
        if let JSON = response.result.value as? [String : Any],
            let places = JSON["places"] as? [[String : String]] {
            for place in places {
                //should I call loadImage() function here?
            }
        }
    }
}

I also have a model for each place in the JSON file:

import UIKit

class Place {

    var name: String
    var url: String

    init?(name: String, url: String) {
        self.name = name
        self.url = url     
    }

}

QUESTION

I'm not sure where to go from here. I would like to use AlamofireImage (which I have included in my project) to download each image but can I do this in a loop of some sort? I would also like to show each image in a new table row. Any advice and code examples would be much appreciated.

Upvotes: 0

Views: 1993

Answers (2)

Rahul
Rahul

Reputation: 2100

I would recommend not fetch the image in loadJSON.

Why?

  • There could be a large number of photos coming back in the initial request, and the user may never even scroll down in the application far enough to see some of them.

  • On top of that, if you initialize too many requests simultaneously, some of the requests may time out while waiting for other requests to finish. So this is probably not the best solution.

So, now coming to the solution. It makes sense to download the image data for only the cells that the user is attempting to view.

TableView has a delegate method for this purpose only

optional func tableView(_ tableView: UITableView, 
        willDisplay cell: UITableViewCell, 
           forRowAt indexPath: IndexPath)

Use this method to load the images.

extension ViewController: UITableViewDelegate {
   func tableView(_ tableView: UITableView, 
        willDisplay cell: UITableViewCell, 
           forRowAt indexPath: IndexPath) {

    let photoURL = places[indexPath.row].url

    // fetch this photo from web using URL

    // get the table view cell and update the image
     if let cell = self.tableView.cellForRow(at: indexPath) as UITableViewCell {
         cell.imageView.image = //fetchPhoto
     }   
    }
}

Upvotes: 1

Nishant Bhindi
Nishant Bhindi

Reputation: 2252

You can use below code in your tableview controller to populate image in cell. For that you will also require to create one cell in tableview or create custom cell with xib. My code is for loading the custom cell from xib take a look.

 //MARK:- TableView Delegate and DataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection sectionIndex: Int) -> Int {
    return places.count
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 200//or cell height you want
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     var cell  = tableView.dequeueReusableCell(withIdentifier: "PlaceCell") as? PlaceCell
    if cell == nil {
        cell = (loadFromNibNamed(viewClass: PlaceCell.self) as! PlaceCell)
    }

    cell?.ivCategory.af_setImage(withURL: URL(string: places[indexPath.row].url)) 
    return cell!
}

Also note that you will have to reload tableview once you get response from api.

Upvotes: 0

Related Questions