skip to Main Content

This is my API: http://swaminarayanwales.org.uk/DailyDarshan/ExportJsonV2.php?sMandir=Nairobi-Temple&Target=real&sm=sm

I AM trying to get images from API in collection view

import UIKit

    struct Images: Decodable {
         let images = [imageUrl]()
     }

     struct imageUrl: Decodable {
        let imageloc: String
      }

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

@IBOutlet weak var CollectionView: UICollectionView!
var imageses = [Images]()
override func viewDidLoad() {
    super.viewDidLoad()
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return imageses.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
     let url = URL(string: "http://swaminarayanwales.org.uk/DailyDarshan/ExportJsonV2.php?sMandir=Nairobi-Temple&Target=real&sm=sm%20)")
    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        guard let data = data else { return }
        do{
            let jsonData =  try JSONDecoder().decode([Images].self, from: data)
            if let imgUrl = URL(string: jsonData[indexPath.row].images[indexPath.row].imageloc){
                if let data = try? Data(contentsOf: imgUrl){
                    cell.imageView.image = UIImage(data: data)
                }
            }
            DispatchQueue.main.async {
                self.collectionView.reloadData()
            }
        }
        catch{
            print("error while decoding")
        }
    }.resume()
    return cell
}

}

i don’t have Xib for collection cell

 import UIKit

 class CollectionViewCell: UICollectionViewCell {

     @IBOutlet weak var ImageView: UIImageView!
 }

when i try to get response from API it gives me proper op in log file so API has no problem

but i am not able to load image response in collection view

i made 2 structure and second structure is used in first as array because in API images is in array form

when i run project i get no output…..

this is the out put of API

{
"mandir": "Nairobi-Temple",
"ShortName": "Nairobi EASST",
"date": "09/01/2021",
"fdate": "09 Jan 21",
"ImageFolder": "DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021",
"images": [{
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//1.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//10.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//11.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//12.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//13.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//14.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//15.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//16.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//2.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//3.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//4.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//5.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//6.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//7.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//8.jpg",
    "imageDimension": "485:1024"
}, {
    "imageloc": "http://swaminarayanwales.org.uk/DailyDarshan/DailyDarshanNairobi-EASST/09-01-2021//9.jpg",
    "imageDimension": "485:1024"
}]
}

MY structure is already mentioned at the top

2

Answers


  1. There are two issues in your code

    1. When you are getting response from the API, you need to populate the array "imageData".

    2. Then you need to reload the collectionView by calling reloadData() method.

    Login or Signup to reply.
  2. There are a few serious design mistakes in your code.

    First of all, never load images synchronously in cellForRow/Item.
    Another mistake is that the root object of the JSON is a dictionary so it’s Images.self

    But first things first.

    Give the structs more meaningful names and decode the url string directly as URL

    struct ImageData : Decodable {
        let images : [Location]
    }
    struct Location: Decodable {
        let imageloc: URL
    }
    

    To load the images asynchronously and not inside the collection view datasource methods use DispatchGroup to load the images one by one and notify when all images are available.

    Declare the data source array as an array of UIImage

    var images = [UIImage]()
    

    and replace callAPI() with

    func callAPI(){
        let url = URL(string: "http://swaminarayanwales.org.uk/DailyDarshan/ExportJsonV2.php?sMandir=Nairobi-Temple&Target=real&sm=sm")!
        
        let task = URLSession.shared.dataTask(with: url){ data, response, error in
            if let error = error { print(error); return }
            do {
                let imageData = try JSONDecoder().decode(ImageData.self, from: data!)
                let imageURLs = imageData.images.map(.imageloc)
                let group = DispatchGroup()
                for imageURL in imageURLs {
                    group.enter()
                    URLSession.shared.dataTask(with: imageURL){ data, response, error in
                        defer{ group.leave() }
                        if let error = error { print(error); return }
                        if let image = UIImage(data: data!) {
                            self.images.append(image)
                        }
                    }.resume()
                    
                }
                group.notify(queue: .main) {
                    self.collectionView.reloadData()
                }
            } catch {
                print(error)
            }
        }
        task.resume()
    }
    

    Now the collection view datasource methods are simply

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return images.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
        cell.imageView.image = images[indexPath.row]
        return cell
    }
    

    Don’t forget to set the identifier of the collection view cell to Cell in Interface Builder.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search