图片未显示在集合中查看Swift

时间:2018-08-07 12:41:18

标签: swift collectionview

在控制台中,有空imageArray的打印,但是我正在downloadImages函数中下载它。在模拟器中,图片将不会加载

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()
    }

}

更新的代码:

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()
}

2 个答案:

答案 0 :(得分:0)

您需要致电

downloadPhoto()

内部

loadItems()

因为两者都是异步的,在这里

self.postsArray.append(post)
downloadPhoto()

注意:我建议在下载图像之前先检查一下缓存,或更好地使用SDWebImage

答案 1 :(得分:0)

正如Sh_Khan所说,您需要在downloadPhoto完成后致电loadItems,否则将没有任何帖子可以循环播放。

此外,这里还有几点要考虑...

  1. 一旦图像下载完成(downloadPhoto),您就不会重新加载任何单元格
  2. 您不缓存图像,因此最终将经常下载图像。滚动collectionView并重新使用单元格后,您将再次下载相同的图像。
  3. 您在这里没有有效地使用DispatchGroup(无论如何在downloadPhoto中),您似乎一次下载了一个映像(或试图这样做),没有利用并行下载的优势。如果您打算这样做,请使用串行队列。但这会大大减慢图像的加载速度。

我更喜欢使用KingFisher来下载和缓存图像,该库已经为您管理了其中的大部分操作,使您可以专注于应用程序。

如果您不想使用一个库,类似的东西应该会帮助您...

var imageCache = [String: UIImage]()

func downloadImage(from url: String){

    if let image = imageCache[url] as? UIImage {
        self.image = image
        return
    }

    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 {
                let image = UIImage(data: data)
                imageCache[url] = image
                self.image = image
            }
        }
    }

    task.resume()
}

Kingfisher示例:

imageView.kf.setImage(with: url, completionHandler: { 
    (image, error, cacheType, imageUrl) in
    // image: Image? `nil` means failed
    // error: NSError? non-`nil` means failed
    // cacheType: CacheType
    //                  .none - Just downloaded
    //                  .memory - Got from memory cache
    //                  .disk - Got from disk cache
    // imageUrl: URL of the image
})

所以有一个postsArray和images数组

var postsArray = [Post]()

var images = [String: UIImage]() // dictionary, maps url to image

然后,当您收到帖子时:

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)
imageView.kf.setImage(with: url, completionHandler: { (image, error, cacheType, imageUrl) in
    // check image is not nil etc
    images[url] = image
    collectionView.reloadData()
}

CellForRowAt:

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

    cell.imgView.image = images[postsArray[indexPath.row].downloadUrl]
    return cell
}