从 iOS CollectionView 中的 API 加载图像

问题描述 投票:0回答:2

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

我正在尝试从集合视图中的 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()
}

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
}

}

我没有 Xib 作为收集单元

 import UIKit

 class CollectionViewCell: UICollectionViewCell {

     @IBOutlet weak var ImageView: UIImageView!
 }

当我尝试从 API 获取响应时,它会在日志文件中为我提供正确的操作,因此 API 没有问题, 但我无法在集合视图中加载图像响应。

我制作了两个结构,第二个结构在第一个结构中用作数组,因为在 API 中图像是数组形式。

当我运行项目时,我没有得到任何输出......

这是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"
}]
}

我的结构已经在顶部提到了。

ios swift image collectionview
2个回答
2
投票

您的代码中存在一些严重的设计错误。

首先,永远不要在

cellForRow/Item
中同步加载图像。 另一个错误是 JSON 的根对象是一个字典,所以它是
Images.self

但首先要注意的事情。

给结构体赋予更有意义的名称,并将 url 字符串直接解码为 URL

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

要异步加载图像而不是在集合视图数据源方法内,请使用

DispatchGroup
一张一张地加载图像,并在所有图像可用时发出通知。

将数据源数组声明为

UIImage

的数组
var images = [UIImage]()

并将

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()
}

现在集合视图数据源方法很简单

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
}

不要忘记在 Interface Builder 中将集合视图单元格的标识符设置为

Cell


0
投票

您的代码中有两个问题

  1. 当您从 API 获取响应时,您需要填充数组“imageData”。

  2. 然后你需要通过调用reloadData()方法重新加载collectionView。

© www.soinside.com 2019 - 2024. All rights reserved.