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()
// Do any additional setup after loading the view, typically from a nib.
callAPI()
}
func callAPI(){
guard let url = URL(string: "http://swaminarayanwales.org.uk/DailyDarshan/ExportJsonV2.php?sMandir=Nairobi-Temple&Target=real&sm=sm") else{
return
}
let task = URLSession.shared.dataTask(with: url){ data, response, error in
if let data = data, let string = String(data: data, encoding: .utf8){
print(string)
}
}
task.resume()
}
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 )")
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.....
CodePudding user response:
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.
CodePudding user response:
There are two issues in your code
When you are getting response from the API, you need to populate the array "imageData".
Then you need to reload the collectionView by calling reloadData() method.