swift: IOS里加载图片到collection view

本文介绍如何在iOS应用中实现TableView内嵌CollectionView,通过调用多个API加载图片到每个CollectionView。首先创建TableView,每个单元格包含一个CollectionView。接着定义数据模型,使用NetworkController进行API请求。在ViewController中实现UITableViewDataSource协议,动态加载不同Category的图片,并使用ImageView缓存防止重复加载。最终实现可滑动的TableView效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我将建一个tableview 并在tableview里放一个collection view,并call很多个api加载图片到每个collection view。首先是UI
在这里插入图片描述
我一会会列出三个不同到种类(category),每一个种类我会建一个array,然后每个array里会有很多张图片的api
下面是我的模型

import Foundation

struct Object: Decodable {
    let hits: [HitsContainer]
}

struct HitsContainer: Decodable {
    let largeImageURL: String
    let likes: Int
    let views: Int
    let type: String
}

然后接着是networkController。用来make api call

import Foundation
import UIKit
class NetworkController {
    
    func callAPI(url: String, completion: @escaping(Data?, Error?) -> Void) {
        guard let url = URL(string: url) else { return }
        URLSession.shared.dataTask(with: url) { (data, _, error) in
            completion(data, error)
        }.resume()
    }

}

首先我call 三个api,并把他们都放到各自的array中,下面所有的代码都在ViewController里面

var objectArray: [HitsContainer] = []
var natureArray: [HitsContainer] = []
var scienceArray: [HitsContainer] = []
var category = ["fashion", "nature", "science", "favorite"]
let netWorkController = NetworkController()
let urlFashionString = "https://pixabay.com/api/?key=13544198-1e8b7d38bdf44ee4a254099f5&category=fashion"

let urlNatureString = "https://pixabay.com/api/?key=13544198-1e8b7d38bdf44ee4a254099f5&category=nature"

let urlScienceString = "https://pixabay.com/api/?key=13544198-1e8b7d38bdf44ee4a254099f5&category=science"

override func viewDidLoad() {
    super.viewDidLoad()
    netWorkController.callAPI(url: urlFashionString) { (data, _) in
        guard let data = data else { return }
        let jsonObject = try? JSONDecoder().decode(Object.self, from: data)
        DispatchQueue.main.async {
            self.objectArray = jsonObject?.hits ?? []
            self.tableView.reloadData()
        }
    }
    netWorkController.callAPI(url: urlNatureString) { (data, _) in
        guard let data = data else { return }
        let jsonObject = try? JSONDecoder().decode(Object.self, from: data)
        DispatchQueue.main.async {
            self.natureArray = jsonObject?.hits ?? []
            self.tableView.reloadData()
        }
    }
    netWorkController.callAPI(url: urlScienceString) { (data, _) in
        guard let data = data else { return }
        let jsonObject = try? JSONDecoder().decode(Object.self, from: data)
        DispatchQueue.main.async {
            self.scienceArray = jsonObject?.hits ?? []
            self.tableView.reloadData()
        }
    }
}

接下来是tableview里用dataSource这个protocol

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return category.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
        cell.categoryLabel.text = category[indexPath.row]
        cell.collectionView.tag = indexPath.row
        cell.collectionView.delegate = self
        cell.collectionView.dataSource = self
        cell.collectionView.reloadData()
        return cell
    }
}

第一个function是我的tableview有多少行,第二个function是设置每行里的cell,需要注意的是我这里用collectionView里的tag等于indexPath.row,方便一会设置那一行对应哪一个collectionView

extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if collectionView.tag == 0 {
            return objectArray.count
        } else if collectionView.tag == 1 {
            return natureArray.count
        } else if collectionView.tag == 2 {
            return scienceArray.count
        } else if collectionView.tag == 3 {
            return favorite?.count ?? 0
        }
        else {
            return 0
        }
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! CollectionViewCell
        if collectionView.tag == 0 {
            let imageURLIndex = objectArray[indexPath.row].largeImageURL
            cell.loadImage(urlString: imageURLIndex)
            cell.labelFavorite.isHidden = true
        } else if collectionView.tag == 1 {
            let imageURLIndex = natureArray[indexPath.row].largeImageURL
            cell.loadImage(urlString: imageURLIndex)
            cell.labelFavorite.isHidden = true
        } else if collectionView.tag == 2 {
            let imageURLIndex = scienceArray[indexPath.row].largeImageURL
            cell.loadImage(urlString: imageURLIndex)
            cell.labelFavorite.isHidden = true
        } else if collectionView.tag == 3 {
            let imageURLIndex = favorite?[indexPath.row].imageurl ?? "errorURL"
            cell.loadImage(urlString: imageURLIndex)
        }
        return cell
    }
}

这里是我设置每一行的collectionView里需要去call category里图片的api,这里我设置了三行category,第四行是我之后会保存到coreData里的图片,这里可以先不理。首先我将每个图片的url等于imageURLIndex,然后在collectionView里用loadImage 更新图片到主要的tableview上,最后是我collectionViewCell的代码

import UIKit

class CollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var image: UIImageView!
    @IBOutlet weak var labelFavorite: UILabel!
    let imageCache = NSCache<NSString, UIImage>()
    
    func getlabelText(text: String) {
        labelFavorite.text = text
    }
    
    func getImage(uiimage: UIImage){
        image.image = uiimage
    }
    
    func loadImage(urlString: String) {
        if let imageFromCache = imageCache.object(forKey: urlString as NSString) {
            DispatchQueue.main.async {
                self.getImage(uiimage: imageFromCache)
            }
        } else {
            guard let url = URL(string: urlString) else { return }
            URLSession.shared.dataTask(with: url) { (data, _, error) in
                guard let data = data,
                let image = UIImage(data: data) else { return }
                self.imageCache.setObject(image, forKey: urlString as NSString)
                DispatchQueue.main.async {
                    self.getImage(uiimage: image)
                }
            }.resume()
        }
    }
}

这里我用loadImage将api得到的data加载到图片里,并用DispatchQueue.main.async更新页面上的图片,同时我也用到了imageCache来防止图片不停的加载。做出来大概是这个样子
在这里插入图片描述
在tableview里有了collectionView,每一行都可以自由来回滑动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值