【问题标题】:Images not showing in UICollectionViewCell’s图像未显示在 UICollectionViewCell 中
【发布时间】:2020-03-16 12:18:20
【问题描述】:

我正在使用 UIKIT 和 Swift 制作一个 iOS 电影应用程序,我想在 collectionview 中显示电影,但是出现了某种故障,并且显示的是某种类型的电影而不是电影。 有人可以帮忙吗?谢谢

moviesViewController.swift

//
//  FirstViewController.swift
//  PopcornTime
//
//  Created by Maxime Ruys on 15/03/2020.
//  Copyright © 2020 Pixel-Developers. All rights reserved.
//

import UIKit
import SwiftyJSON

class MoviesViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    @IBOutlet weak var moviesCollectionView: UICollectionView!

    var movies = [Movie]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.moviesCollectionView.delegate = self
        self.moviesCollectionView.dataSource = self

        fetchMovies()

    }

    func fetchMovies(){

        self.movies = []

        let url = URL(string: "API_URL_HERE")

        guard let requestUrl = url else { fatalError() }

        var request = URLRequest(url: requestUrl)
        request.httpMethod = "GET"

        request.httpBody = "".data(using: String.Encoding.utf8)

        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in

            if (error != nil) {
                print(error)
            } else {

                if let data = data, let dataString = String(data: data, encoding: .utf8) {

                    do {

                        if let dataFromString = dataString.data(using: .utf8, allowLossyConversion: false) {

                            let json = try JSON(data: dataFromString)

                            for(_, movie) in json{

                                var imgs = [String]()

                                imgs.append(movie["images"]["banner"].stringValue)
                                imgs.append(movie["images"]["poster"].stringValue)
                                imgs.append(movie["images"]["fanart"].stringValue)

                                self.movies.append(Movie(id: movie["_id"].stringValue, title: movie["title"].stringValue, desc: movie["synopsis"].stringValue, playTime: movie["runtime"].stringValue, imgs: imgs))

                            }

                        }

                    } catch {
                        print(error)
                    }

                    DispatchQueue.main.async {
                        self.moviesCollectionView.reloadData()
                    }

                }

            }

        }

        task.resume()

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.movies.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MoviesRowController",
                                                      for: indexPath) as! MoviesRowController

        cell.moviesRowImg.image = downloadImage(from: URL(string: movies[indexPath.row].imgs[0])!)
        cell.moviesTitleLbl.text = movies[indexPath.row].title

        return cell

    }

    func downloadImage(from url: URL) -> UIImage{
        getData(from: url) { data, response, error in
            guard let data = data, error == nil else { return }
            DispatchQueue.main.async() {
                return UIImage(data: data)
            }
        }
        return UIImage(named: "test")!
    }

    func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
        URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
    }

}

collectionview 故障图像:

collectionview 属性:

colletionview 单元格属性:

【问题讨论】:

  • 从网址下载后,请检查您是否获得了正确的图像。在return UIImage(data: data) 中放置一个断点,看看会发生什么。
  • @iPeter 我已经尝试使用普通图像,它仍然会显示三角形。
  • 如果您在图像数组中有图像 URL,那么 SDWebImage 会对您有很大帮助。检查此链接:github.com/SDWebImage/SDWebImage

标签: ios swift uicollectionview uicollectionviewcell


【解决方案1】:

你不能分配一个异步的值,所以这里的 return 是 nil

func downloadImage(from url: URL) -> UIImage{
    getData(from: url) { data, response, error in
        guard let data = data, error == nil else { return }
        DispatchQueue.main.async() {
            return UIImage(data: data)
        }
    }
    return UIImage(named: "test")
}

使用SDWebImage

【讨论】:

    【解决方案2】:

    你可以像下面这样进行自省。

    if movies[indexPath.row].imgs.count>0, let url = URL(string: movies[indexPath.row].imgs[0]!) {
        }
    

    如果您希望缓存图像以避免多次请求,请使用以下扩展。

    let imageCache = NSCache<NSString, UIImage>()
    
    extension UIImageView {
    
    func imageFromServerURL(_ URLString: String, placeHolder: UIImage?) {
    
        self.image = nil
        if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
            self.image = cachedImage
            return
        }
    
        if let url = URL(string: URLString) {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
    
                //print("RESPONSE FROM API: \(response)")
                if error != nil {
                    print("ERROR LOADING IMAGES FROM URL: \(error)")
                    DispatchQueue.main.async {
                        self.image = placeHolder
                    }
                    return
                }
                DispatchQueue.main.async {
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }}
    

    【讨论】:

    • 感谢这至少解决了三角形。但单元格的大小与必须的不同。
    • 这将多次下载图像,可能同时您需要现金使用SDwebimage,正如我在我的回答中所说的那样
    • @navroz 起初它可以工作,但现在它给了我一个致命错误,并说在我添加代码行来注册我的单元格后图像为零。 ibb.co/x3Qm5Dwibb.co/Cw0bQjn
    • 首先您需要检查哪个值是 nil 以防 imgs[0] 导致它,然后您必须对其进行检查。在编辑的答案中提到。否则,您在配置单元格时做错了。
    【解决方案3】:

    您的手机也未注册:

        self.collectionView.register(UICollectionViewCell.self, forCellReuseIdentifier: "movieCell")
    

    【讨论】:

    • 谢谢,我怎么会忘记这一点。可能是因为过去一年我没有制作任何 iOS 应用程序。谢谢
    • 实际上我不必这样做,否则我会覆盖当前单元格属性,因为我使用的是情节提要,而这次我没有以编程方式进行
    • aaaah 好的,那么抱歉,我使用以编程方式创建所有视图,但我在代码中错过了它
    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    相关资源
    最近更新 更多