Search code examples
swiftcollectionview

Images not showing in collectionView Swift


In console there is printing of empty imagesArray but I am downloading it in downloadImages function. And in simulator the images won't load

import UIKit
import PinterestLayout
import ProgressHUD

class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    var postsArray = [Post]()

    var imagesArray = [UIImage]()

    override func viewDidLoad() {
        super.viewDidLoad()

       if let layout = collectionView.collectionViewLayout as? PinterestLayout {
            layout.delegate = self
        }

        collectionView.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

        loadItems()
        downloadPhoto()

    }

    func loadItems() {
        ref.child("Posts").observe(.childAdded) { (snapshot) in

            let snapshotValue = snapshot.value as! Dictionary<String,Any>

            if let title = snapshotValue["title"], let price = snapshotValue["price"], let downloadUrl = snapshotValue["downloadUrl"], let category = snapshotValue["category"], let senderUid = snapshotValue["senderUid"] {

                let post = Post()
                post.title = title as! String
                post.price = price as! String
                post.downloadUrl = downloadUrl as! String
                post.category = category as! String
                post.senderUid = senderUid as! String

                self.postsArray.append(post)

                self.collectionView.reloadData()

            }
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tabBarController?.tabBar.shadowImage = UIImage()
        tabBarController?.tabBar.backgroundImage = UIImage()


    }

    func downloadPhoto(){
        DispatchQueue.global().async {
            self.imagesArray.removeAll() // this is the image array

            for i in 0..<self.postsArray.count {
                guard let url = URL(string: self.postsArray[i].downloadUrl) else {
                    continue
                }

                let group = DispatchGroup()

                print(url)
                print("-------GROUP ENTER-------")

                group.enter()
                URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
                    print(response?.suggestedFilename ?? url.lastPathComponent)

                    if let imgData = data, let image = UIImage(data: imgData) {
                        DispatchQueue.main.async() {
                            self.imagesArray.append(image)
                            self.collectionView.reloadData()
                        }
                    } else if let error = error {
                        print(error)
                    }

                    group.leave()
                }).resume()

                group.wait()
            }
        }
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imagesArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell

        cell.imgView.downloadImage(from: self.postsArray[indexPath.row].downloadUrl)

        return cell
    }



}

extension MainViewController: PinterestLayoutDelegate {

    func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {

        let image = imagesArray[indexPath.item]
        let height = image.size.height

        return height

    }
}

extension UIImageView {

    func downloadImage(from url: String){

        let urlRequest = URLRequest(url: URL(string: url)!)

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

            if error != nil {
                print(error ?? error!)
                return
            }
            if let data = data {
                DispatchQueue.main.async {
                    self.image = UIImage(data: data)
                }
            }
        }
        task.resume()
    }

}

UPDATED CODE:

import UIKit
import PinterestLayout
import ProgressHUD
import Kingfisher

class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    var postsArray = [Post]()

    var imagesArray = [UIImage]()

    override func viewDidLoad() {
        super.viewDidLoad()

       if let layout = collectionView.collectionViewLayout as? PinterestLayout {
            layout.delegate = self
        }

        collectionView.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

        loadItems()


        collectionView.reloadData()
    }

    func loadItems() {
        ref.child("Posts").observe(.childAdded) { (snapshot) in

            let snapshotValue = snapshot.value as! Dictionary<String,Any>

            if let title = snapshotValue["title"], let price = snapshotValue["price"], let downloadUrl = snapshotValue["downloadUrl"], let category = snapshotValue["category"], let senderUid = snapshotValue["senderUid"] {

                let post = Post()
                post.title = title as! String
                post.price = price as! String
                post.downloadUrl = downloadUrl as! String
                post.category = category as! String
                post.senderUid = senderUid as! String

                self.postsArray.append(post)
                self.downloadPhoto()

                print(self.imagesArray.count)

                self.collectionView.reloadData()

            }
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tabBarController?.tabBar.shadowImage = UIImage()
        tabBarController?.tabBar.backgroundImage = UIImage()

    }

    func downloadPhoto(){
        DispatchQueue.global().async {
            self.imagesArray.removeAll() // this is the image array

            for i in 0..<self.postsArray.count {
                guard let url = URL(string: self.postsArray[i].downloadUrl) else {
                    continue
                }

                let group = DispatchGroup()

                print(url)
                print("-------GROUP ENTER-------")

                group.enter()
                URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in
                    print(response?.suggestedFilename ?? url.lastPathComponent)

                    if let imgData = data, let image = UIImage(data: imgData) {
                        DispatchQueue.main.async() {
                            self.imagesArray.append(image)
                            let post = Post()
                            post.image = image
                            self.collectionView.reloadData()
                        }
                    } else if let error = error {
                        print(error)
                    }
                    group.leave()
                }).resume()

                group.wait()
            }

        }
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return postsArray.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mainCell", for: indexPath) as! MainCollectionViewCell

        let resource = ImageResource(downloadURL: URL(string: postsArray[indexPath.row].downloadUrl)!, cacheKey: postsArray[indexPath.row].downloadUrl)
        cell.imgView.kf.setImage(with: resource)

        return cell
    }



}

extension MainViewController: PinterestLayoutDelegate {

    func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {

        let image = imagesArray[indexPath.row]
        let height = image.size.height / 6

        return height

    }
}
//AND POST CLASS

import UIKit

    class Post {
    var title : String = ""
    var category : String = ""
    var downloadUrl : String = ""
    var price : String = ""
    var senderUid : String = ""
    var image = UIImage()
}

Solution

  • You need to call

    downloadPhoto()
    

    inside

    loadItems()
    

    as both are asynchronous , here

    self.postsArray.append(post)
    downloadPhoto()
    

    Note: I recommend having a cache to check before downloading the image or better use SDWebImage