【问题标题】:CollectionView Cell and Progress Bar - Progress Bar showing in wrong Cell after scrollingCollectionView 单元格和进度条 - 滚动后进度条显示在错误的单元格中
【发布时间】:2017-01-28 04:33:10
【问题描述】:

我这几天一直在寻找这个问题的答案,但似乎无法弄清楚。我有一个带有自定义单元格的集合视图。当您在收藏视图中双击一个单元格时,它会下载一个文件,如果之前下载过,则将其删除。

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

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

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

我不知道这是否是我如何重用单元格的错误???它似乎与我如何更新单元格或集合视图无关,这在所有情况下都有效,除了滚动之后。

下面是两个下载或删除文件的函数:

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
} 

【问题讨论】:

    标签: swift uicollectionview uiprogressview


    【解决方案1】:

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

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

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

    您需要确保正确维护您从中提供 collectionview 数据的数组。例如,如果你有一个数组 A =[1,2,3],你删除了 A[1],那么数组 A 需要是 [1,3]。

    【讨论】:

    • 我有点不确定你的意思,在添加任何额外的 ui 元素之前将单元格重置为默认状态。我已将我的 cellForItemAt 函数附加到原始问题......所以它的作用是使用登录时构建的数组来填充主图像(绿色 1 - 2 等)和其他地方使用的一些其他数据。然后(这是我之前唯一这样做过的地方)它在本地设备中查询文件名(来自上述数组)以查看它是否存在......
    • 主要问题中的函数(downloadDataToDevice 和 removeDataFromDevice)从本地设备和本地数据表中添加或删除此数据,所以我认为这可以处理您提到的维护部分。我想在需要时以编程方式将 ui 元素添加到所需的单元格可能是一种更准确的方法。
    【解决方案2】:

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

    似乎有效的方法是在进度块中重新定位单元

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-07
      • 1970-01-01
      • 2012-04-05
      • 1970-01-01
      • 2023-04-02
      • 2018-09-11
      相关资源
      最近更新 更多