Search code examples
iosswiftuicollectionviewuicollectionviewcell

Images not showing in UICollectionViewCell’s


I am making an iOS movie app using UIKIT and Swift and I wanted to display the movies in a collectionview but there's some kind of glitch and there are some kind of traingle being diplayed instead of the movie. Could someone please help? Thanks

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 glitch image: enter image description here

collectionview properties: enter image description here

colletionview cell properties: enter image description here


Solution

  • You can't assign a value that's asynchronous , so return here is 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")
    }
    

    use SDWebImage