You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在UICollectionView中从API加载图片URL数组的问题求助

问题分析与修复方案

核心问题梳理

  • 数据模型数组定义错误:原代码用[Welcome]存储数据,但实际需要的是Welcome结构体里的[Location]数组,数组类型定义错误导致无法正确访问图片地址。
  • API请求位置错误:把网络请求放在cellForItemAt中,会导致每个cell显示时重复发起API请求,既浪费资源,还会因cell复用导致图片显示混乱。
  • URL语法错误:原API地址字符串末尾多了一个),导致URL(string:)创建失败,直接引发崩溃。
  • 图片加载方式错误:用try? Data(contentsOf:)同步加载图片,会阻塞后台线程影响性能,且未处理cell复用问题。
  • 未设置CollectionView代理:viewDidLoad中未给collectionView设置delegate和dataSource,可能导致数据源方法不执行。

修正后的完整代码

ViewController代码

import UIKit

struct Welcome: Decodable {
    let images: [Location]
}

struct Location: Decodable {
    let imageloc: String
}

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    // 修正:存储Location数组,对应API返回的images列表
    var imageLocations: [Location] = []
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置代理和数据源
        collectionView.delegate = self
        collectionView.dataSource = self
        // 发起API请求获取数据
        fetchImageData()
    }
    
    // 单独封装API请求方法
    private func fetchImageData() {
        // 修正URL:去掉末尾多余的`)`
        guard let url = URL(string: "http://swaminarayanwales.org.uk/DailyDarshan/ExportJsonV2.php?sMandir=Nairobi-Temple&Target=real&sm=sm") else {
            print("无效的API地址")
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            
            if let error = error {
                print("请求错误:\(error.localizedDescription)")
                return
            }
            
            guard let data = data else {
                print("未获取到数据")
                return
            }
            
            do {
                let welcomeData = try JSONDecoder().decode(Welcome.self, from: data)
                // 保存获取到的图片地址数组
                self.imageLocations = welcomeData.images
                // 回到主线程刷新CollectionView
                DispatchQueue.main.async {
                    self.collectionView.reloadData()
                }
            } catch {
                print("解析错误:\(error.localizedDescription)")
            }
        }.resume()
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // 返回图片地址数组的数量
        return imageLocations.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
        
        // 先设置默认图片,避免复用显示旧内容
        cell.imageView.image = UIImage(systemName: "photo")
        
        let location = imageLocations[indexPath.row]
        guard let imgUrl = URL(string: location.imageloc) else {
            print("无效的图片地址:\(location.imageloc)")
            return cell
        }
        
        // 异步加载图片,处理cell复用问题
        URLSession.shared.dataTask(with: imgUrl) { [weak cell] data, _, error in
            if let error = error {
                print("图片加载错误:\(error.localizedDescription)")
                return
            }
            
            guard let data = data, let image = UIImage(data: data) else { return }
            
            DispatchQueue.main.async {
                // 确保cell未被复用才设置图片
                if let currentCell = cell, currentCell == collectionView.cellForItem(at: indexPath) {
                    currentCell.imageView.image = image
                }
            }
        }.resume()
        
        return cell
    }
}

CollectionViewCell代码(无需修改,需确认IBOutlet关联正确)

import UIKit

class CollectionViewCell: UICollectionViewCell {
     @IBOutlet weak var imageView: UIImageView!
}

关键修改说明

  1. 修正数据存储数组:将var imageloc = [Welcome]()改为var imageLocations: [Location] = [],直接存储API返回的图片地址列表,方便后续访问imageloc属性。
  2. API请求移至viewDidLoad:单独封装fetchImageData方法,页面加载时仅发起一次请求,获取数据后刷新CollectionView,避免重复请求。
  3. 修复URL错误:移除原URL末尾多余的),确保URL能正确创建。
  4. 优化图片加载:用URLSession异步加载图片,通过判断当前cell是否仍对应原indexPath,避免cell复用导致图片显示错位;同时设置默认图片提升用户体验。
  5. 设置CollectionView代理:在viewDidLoad中添加collectionView.delegate = self和collectionView.dataSource = self,确保数据源方法正常执行。

内容的提问来源于stack exchange,提问作者heli bhadeshiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:06:28