CollectionView单元格和进度条 - 滚动后显示错误单元格的进度条

时间:2017-01-28 04:33:11

标签: swift uicollectionview uiprogressview

我几天来一直在寻找这个问题的答案,似乎无法弄明白。我有一个自定义单元格的集合视图。当您在“收集视图”中双击一个单元格时,它将下载文件或删除它,如果之前已下载过。

在下载过程中,进度条显示下载进度,然后在左上角显示一个小图标。删除时删除图标。

enter image description here

如果您从一个单元格下载并在第一次下载过程中从另一个单元格中删除它可以正常工作,但前提是这两个单元格在集合视图中都可见。

enter image description here

如果我从一个单元格下载,然后滚动屏幕并从与正在下载的单元格不在同一屏幕中的单元格中删除,它会像往常一样删除角落图像,然后显示单元格的进度条正在下载。

enter image description here

我不知道这是否是我重复使用细胞的错误???它似乎与我如何更新除了滚动之外的所有情况下都适用的单元格或集合视图有任何关系。

以下是2个下载或删除文件的功能:

func downloadDataToDevice(cell: JourneyCollectionViewCell, selectedIndexPath: IndexPath){

    let downloadedAudio = PFObject(className: "downloadedAudio")
    // save all files with unique name / object id
    let selectedObjectId = self.partArray[selectedIndexPath.item].id
    let selectedPartName = self.partArray[selectedIndexPath.item].name

    let query = PFQuery(className: "Part")
    query.whereKey("objectId", equalTo: selectedObjectId)
    query.getFirstObjectInBackground { (object, error) in

        if error != nil || object == nil {
            print("No object for the index selected.")
        } else {
            //print("there is an object, getting the file.")
            downloadedAudio.add(object?.object(forKey: "partAudio") as! PFFile, forKey: selectedPartName)
            let downloadedFile = object?.object(forKey: "partAudio") as! PFFile

            // get the data first so we can track progress
            downloadedFile.getDataInBackground({ (success, error) in
                if (success != nil) {
                    // pin the audio if there is data
                    downloadedAudio.pinInBackground(block: { (success, error) in
                        if success {

                            // reload the cell
                            self.reloadCell(selectedIndexPath: selectedIndexPath, hideProgress: true, hideImage: false, cell: cell)
                            self.inProgress -= 1
                            cell.isUserInteractionEnabled = true

                        }
                    })
                }
            // track the progress of the data
            }, progressBlock: { (percent) in
                self.activityIndicatorView.stopAnimating()
                cell.progessBar.isHidden = false
                //cell.progessBar.transform = cell.progessBar.transform.scaledBy(x: 1, y: 1.1)
                cell.contentView.bringSubview(toFront: cell.progessBar)
                cell.progessBar.setProgress(Float(percent) / Float(100), animated: true)
                cell.isUserInteractionEnabled = false
            })
        }
    }
}

func removeDataFromDevice(cell: JourneyCollectionViewCell, selectedIndexPath: IndexPath, object: PFObject) {

        let selectedPartName = self.partArray[selectedIndexPath.item].name

        // unpin the object from the LocalDataStore
        PFObject.unpinAll(inBackground: [object], block: { (success, error) in
            if success {
                // reduce inProgress
                self.inProgress -= 1
                self.reloadCell(selectedIndexPath: selectedIndexPath, hideProgress: true, hideImage: true, cell: cell)
            }
        })
}

这就是我重新加载单元格的方式

func reloadCell(selectedIndexPath: IndexPath, hideProgress: Bool, hideImage: Bool, cell: JourneyCollectionViewCell) {
    cell.progessBar.isHidden = hideProgress
    cell.imageDownloaded.isHidden = hideImage
    self.collectionView.reloadItems(at: [selectedIndexPath])
}

-----------编辑-------------

这是我的cellForItem函数。目前我正在使用查询查看本地驱动器,看看文件是否存在,然后添加角落图像(如果是)。这是我第一次在这个地方使用查询,通常它是一个登录时填充数组的查询,但这是一个比我想通过让用户下载和删除我想要实现的数据更静态的数据集合文件。

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

    let cell: JourneyCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! JourneyCollectionViewCell

        cell.imageCell.file = self.partArray[indexPath.item].image
        cell.imageCell.loadInBackground()
        cell.imageCell.layer.masksToBounds = true

    // not sure if its good to run a query here as its constantly updated.
    // query if file is on LDS and add image to indicate
    let cellPartName = self.partArray[indexPath.item].name
    let checkQuery = PFQuery(className: "downloadedAudio")
        checkQuery.whereKeyExists(cellPartName)
        checkQuery.fromLocalDatastore()
        checkQuery.getFirstObjectInBackground(block: { (object, error) in
        if error != nil || object == nil {
            //print("The file does not exist locally on the device, remove the image.")
            cell.imageDownloaded.isHidden = true
            cell.imageDownloaded.image = UIImage(named: "")
            cell.progessBar.isHidden = true

        } else {
            //print("the file already exists on the device, add the image.")
            cell.contentView.bringSubview(toFront: cell.imageDownloaded)
            cell.imageDownloaded.isHidden = false
            cell.imageDownloaded.image = UIImage(named: "download-1")

            }
        })
    return cell
} 

2 个答案:

答案 0 :(得分:3)

这是"重用"的正常功能。单元,用于有效的内存管理目的。您需要做的是重置以下函数中的单元格值:

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

通过重置,我的意思是在您进行任何更新(例如添加左角图标或状态栏)之前将单元格设置为其默认状态。

您需要确保正在为正在提供集合视图数据的阵列进行维护。例如,如果你有一个数组A = [1,2,3]并删除A [1],那么数组A必须是[1,3]。

答案 1 :(得分:1)

所以我尝试以编程方式放置进度视图,我在自定义单元类中尝试了prepareForReuse,但没有直接解决这个问题,尽管我会继续使用prepareForReuse,因为我认为它比以前更清晰地管理单元格。 / p>

似乎有用的是在progressBlock中重新定位单元格

if let downloadingCell = self.collectionView.cellForItem(at: selectedIndexPath) as? JourneyCollectionViewCell {                            downloadingCell.progessBar.isHidden = false
    downloadingCell.contentView.bringSubview(toFront: downloadingCell.progessBar)
    downloadingCell.progessBar.setProgress(Float(percent) / Float(100), animated: true)
    downloadingCell.setNeedsDisplay()
    downloadingCell.isUserInteractionEnabled = false
}

enter image description here