使用Swift 3显示Image时,UICollection非常慢

时间:2017-03-29 08:31:10

标签: swift3 uicollectionview uicollectionviewcell uicollectionviewlayout uicollectionviewdelegate

我使用UICollectionView在我的应用中显示图像 问题是显示图像需要很慢。 50秒后,将显示集合视图中的图像。 :(
当我在谷歌找到解决方案时,他们大多写下面的代码。
但对我来说, 无法正常工作

  cell.layer.shouldRasterize = true
  cell.layer.rasterizationScale = UIScreen.main.scale

extension SeeAllCollectionView {

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    debugPrint("seeAllLIStCell Count \(assetsTable.count)")
    return assetsTable.count
}

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


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

    let list = assetsTable[(indexPath as NSIndexPath).row]


    var imageName: String? = (list.poster_image_url)
    var image: UIImage? = (images_cache[imageName!])
    if image != nil {
        debugPrint("Yes Image")

        cell.imageView.image = image

    } else{
        debugPrint("NO Image")
        cell.imageView.image = nil

        DispatchQueue.main.async(){
            let url = NSURL(string: list.poster_image_url)
            let data = NSData(contentsOf:url! as URL)
            var image = UIImage(data: data as! Data)
            DispatchQueue.main.async(execute: {() -> Void in
                cell.movieTitle.text = list.name
                cell.imageView?.image = image
            })
            self.images_cache[imageName!] = image
        }

    }




    return cell
}

}


// MARK: - UICollectionViewDelegate

extension SeeAllCollectionView {

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

            debugPrint("Selected")


    let list = assetsTable[(indexPath as NSIndexPath).row]
    debugPrint(list.poster_image_url)
    debugPrint(list.name)

    prefs.set(list.poster_image_url, forKey: "poster_image_url")
    prefs.set(list.name, forKey: "name")
    prefs.set(list.assets_id, forKey: "VIDEO_ID")
    prefs.set(false, forKey: "FLAG")
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "DetailsChannel") as UIViewController
            self.present(vc, animated: true, completion: nil)

}

}

这是我运行项目时的屏幕截图。我跑的时候得到了这么多行代码。

enter image description here

请有人帮我,我该怎么办?

3 个答案:

答案 0 :(得分:0)

当我从API调用中获取数据并重新加载console error时(根据我的要求),我得到了相同的UITableView。我的问题通过使用

解决了
DispatchQueue.global(qos: .background).async { // load data in back ground mode so that main thread can be safed.
let url = NSURL(string: list.poster_image_url)
            let data = NSData(contentsOf:url! as URL)
            var image = UIImage(data: data as! Data)
    DispatchQueue.main.async(execute: {
                                cell.movieTitle.text = list.name
                cell.imageView?.image = image
                            }) 
self.images_cache[imageName!] = image       
        }

我之前在我的控制台上出现的错误的屏幕截图

enter image description here

答案 1 :(得分:0)

这一行:

DispatchQueue.main.async()

下载图像时可能会导致错误,它会阻塞主线程并在主(UI)队列上执行网络请求,更不用说这些请求随后是串行执行的(因此很慢)。尝试将代码段更改为:

DispatchQueue.global.async(qos: DispatchQoS.QoSClass.background){
        let url = NSURL(string: list.poster_image_url)
        let data = NSData(contentsOf:url! as URL)
        var image = UIImage(data: data as! Data)
        DispatchQueue.main.async(execute: {() -> Void in

其中global代表此类网络操作的全局队列默认值。

编辑:除了使用主队列进行网络调用之外,实际上可能存在的问题实际上是为屏幕上当前不可见的行加载了太多图像。如果它们很多并且连接不是那么好,那么最终会有屏幕上单元格的应用程序待处理下载。考虑仅为屏幕上的单元格延迟加载图像 - 并取消不可见的行的下载。在Swift中有一个非常好的tutorial(但是对于表视图,但你可以很容易地扩展它来收集)如何实现这一点。

答案 2 :(得分:0)

您可以尝试SDWebimage保持所有异步线程操作。

这可以提供以下优势

异步下载

如果应用程序发生内存警告,则自动清除图像缓存

图片网址缓存

图像缓存

避免重复下载

您可以直接在单元格中使用单个方法,如下所示

[cell.storeImg sd_setImageWithURL:[NSURL URLWithString:strURL] placeholderImage:kDefaultImageForDisplay];

在你的代码中,后续行应该会产生问题,因为该操作可能发生在主线程上  let data = NSData(contentsOf:url!as URL)