将图像从Parse加载到UICollectionView单元格而不会延迟

时间:2015-09-26 15:52:25

标签: ios swift parse-platform

我有一个相当精细的问题,我认为具有广泛异步知识的人可以帮助我。

我有一个collectionView,其中填充了" Picture"对象。这些对象是从自定义类创建的,然后再次使用从Parse(来自PFObject)获取的数据填充这些对象。

首先,查询Parse

func queryParseForPictures() {
    query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, err: NSError?) -> Void in
        if err == nil {
            print("Success!")
            for object in objects! {
                let picture = Picture(hashtag: "", views: 0, image: UIImage(named: "default")!)
                picture.updatePictureWithParse(object)
                self.pictures.insert(picture, atIndex: 0)
            }
            dispatch_async(dispatch_get_main_queue()) { [unowned self] in
                self.filtered = self.pictures
                self.sortByViews()
                self.collectionView.reloadData()
            }
        }
    }
}

现在我在PFObject中也得到了一个PFFile,但看到将PFFile转换为NSData也是一个异步调用(同步会阻止整个事情..),我无法弄清楚如何正确加载它。函数" picture.updatePictureWithParse(PFObject)"更新除了UIImage之外的所有其他内容,因为其他值是基本的字符串等。如果我也在这个函数中从PFFile获取NSData,那么" collectionView.reloadData()"在图片加载之前会关闭,我最终会得到一堆没有图像的图片。除非我强行重装后或其他什么。因此,我将PFFile存储在对象中以供将来在updatePictureWithParse中使用。这是Picture类中的超级简单函数:

func updateViewsInParse() {
    let query = PFQuery(className: Constants.ParsePictureClassName)
    query.getObjectInBackgroundWithId(parseObjectID) { (object: PFObject?, err: NSError?) -> Void in
        if err == nil {
            if let object = object as PFObject? {
                object.incrementKey("views")
                object.saveInBackground()
            }
        } else {
            print(err?.description)
        }
    }
}

为了半透明地获取图像,我已经在cellForItemAtIndexPath中实现了图像的加载,但这太可怕了。它适用于前10个或者其他任何东西,但是当我向下滚动视图时它会滞后很多,因为它必须从Parse获取下一个单元格。请参阅下面的实施:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(Constants.PictureCellIdentifier, forIndexPath: indexPath) as! PictureCell

    cell.picture = filtered[indexPath.item]

    // see if image already loaded
    if !cell.picture.loaded {
        cell.loadImage()
    }
    cell.hashtagLabel.text = "#\(cell.picture.hashtag)"
    cell.viewsLabel.text = "\(cell.picture.views) views"
    cell.image.image = cell.picture.image

    return cell
}

实际的获取位于单元格内:

func loadImage() {
    if let imageFile = picture.imageData as PFFile? {
        image.alpha = 0
        imageFile.getDataInBackgroundWithBlock { [unowned self] (imageData: NSData?, err: NSError?) -> Void in
            if err == nil {
                self.picture.loaded = true
                if let imageData = imageData {
                    let image = UIImage(data: imageData)
                    self.picture.image = image
                    dispatch_async(dispatch_get_main_queue()) {
                        UIView.animateWithDuration(0.35) {
                            self.image.image = self.picture.image
                            self.image.alpha = 1
                            self.layoutIfNeeded()
                        }
                    }
                }
            }
        }
    }
}

我希望你能感受到我的问题。在单元格内部取出图像是非常糟糕的。此外,如果这几个片段并未提供完整的图片,请参阅该项目的github链接: https://github.com/tedcurrent/Anonimg

全部谢谢!

/ T

1 个答案:

答案 0 :(得分:1)

可能有点迟了但是当在UICollectionView中从数据库加载PFImageView时,我发现这种方法效率更高,虽然我不完全确定原因。我希望它有所帮助。使用cellForItemAtIndexPath代替cell.loadImage()功能。

if let value = filtered[indexPath.row]["imageColumn"] as? PFFile {
    if value.isDataAvailable {
        cell.cellImage.file = value       //assign the file to the imageView file property
        cell.cellImage.loadInBackground() //loads and does the PFFile to PFImageView conversion for you
    }
}