简体   繁体   English

在 collectionview ios 中从 API 加载图像

[英]loading images from API in collectionview ios

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

I AM trying to get images from API in collection view我正在尝试从集合视图中的 API 获取图像

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%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我没有用于收集单元的 Xib

 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当我尝试从 API 获得响应时,它在日志文件中给了我正确的操作,所以 API 没有问题

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我做了 2 个结构,第二个结构首先用作数组,因为在 API 中,图像是数组形式

when i run project i get no output.....当我运行项目时,我没有得到 output .....

There are a few serious design mistakes in your code.您的代码中有一些严重的设计错误。

First of all, never load images synchronously in cellForRow/Item .首先,永远不要在cellForRow/Item中同步加载图像。 Another mistake is that the root object of the JSON is a dictionary so it's Images.self另一个错误是 JSON 的根 object 是字典,所以它是Images.self

But first things first.但首先要做的事情。

Give the structs more meaningful names and decode the url string directly as URL为结构赋予更有意义的名称并将 url 字符串直接解码为 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.要异步加载图像而不是在集合视图数据源方法中,请使用DispatchGroup一张一张地加载图像并在所有图像可用时通知。

Declare the data source array as an array of UIImage将数据源数组声明为UIImage的数组

var images = [UIImage]()

and replace callAPI() with并将callAPI()替换为

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.不要忘记在 Interface Builder 中将集合视图单元格的标识符设置为Cell

There are two issues in your code您的代码中有两个问题

  1. When you are getting response from the API, you need to populate the array "imageData".当您收到来自 API 的响应时,您需要填充数组“imageData”。

  2. Then you need to reload the collectionView by calling reloadData() method.然后您需要通过调用 reloadData() 方法重新加载 collectionView。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM