UICollectionView CustomCell 重用

UICollectionView CustomCell ReUse

我正在获取用户的 Photo Asset 并尝试在我的 UICollectionView 中创建自定义 UICollectionViewCell,其中第一个索引是 Camera Image,其他单元格是相机图像.但是当我滚动时,就像重新创建了索引处的图像,我注意到单元格中的一些图像得到了我在 index[0]

添加的视图
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    //Deque an GridViewCell
    let cell: GridViewCell = (collectionView.dequeueReusableCellWithReuseIdentifier(CellReuseIdentifier, forIndexPath: indexPath) as? GridViewCell)!
    if indexPath.item != 0 {

        let asset = assetsFetchResults[indexPath.item - 1] as! PHAsset
        cell.representedAssetIdentifier = asset.localIdentifier

        imageManager.requestImageForAsset(asset, targetSize: AssetGridThumbnailSize, contentMode: PHImageContentMode.AspectFill, options: nil) { (result: UIImage?, info: [NSObject : AnyObject]?) -> Void in
            //print(result)
            if cell.representedAssetIdentifier.isEqualToString(asset.localIdentifier) {
                if let imageResult = result {
                    cell.imageView.image = imageResult
                }
            }
        }
    } else {
        let cameraButton = UIButton(frame: CGRectMake(0,0,80,80))
        cameraButton.setTitle("Camera", forState: .Normal)
        cameraButton.frame = cell.imageView.bounds
        cell.imageView.addSubview(cameraButton)
    }

    return cell
}

下图为说明

可重复使用的单元格在滚动到视图外时会被集合视图重复使用,以防止大量内存使用。当某个单元格滚动到视图之外时,集合视图会将它们标记为可重用。可重用的单元格将被集合视图重用,而不是创建新的单元格。这将显着减少内存使用。如果同时只有 20 个单元格适合屏幕,为什么要在内存中保留 1000 个单元格。

因为单元格被重用,它们仍然会包含前一个单元格的内容,这意味着单元格仍然有 cameraButton 作为子视图。与图像相同的故事,您需要手动将它们从单元格中删除,并确保替换或删除所有旧内容。

当您执行将图像下载并在一段时间后设置到单元格的方法时,该单元格可能仍包含前一个单元格的图像。您应该清除 cellForRowAtIndexPath 方法开头的图像以删除旧的 image/subviews.

参见下面的示例:

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! GridViewCell


    if indexPath.row == 0 {
        // Show the title becouse it's the first cell.
        cell.titleLabel.hidden = false

        // Title needs to be set in storyboard
        // Default image for camera roll needs to be set in storyboard

    } else {
        // All the other cells.
        cell.titleLabel.hidden = true

        // Clear old content
        cell.imageView.image = nil

        // I don't exactly know what all this code does behind the screen, but I assume it's a method that downloads the image and add it to the imageView when it's done.
        let asset = assetsFetchResults[indexPath.item - 1] as! PHAsset
        cell.representedAssetIdentifier = asset.localIdentifier

        imageManager.requestImageForAsset(asset, targetSize: AssetGridThumbnailSize, contentMode: PHImageContentMode.AspectFill, options: nil) { (result: UIImage?, info: [NSObject : AnyObject]?) -> Void in
            //print(result)
            if cell.representedAssetIdentifier.isEqualToString(asset.localIdentifier) {
                if let imageResult = result {
                    cell.imageView.image = imageResult
                }
            }
        }
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    // Cell that needs to open the camera roll when tapped)
    if indexPath.row == 0 {

        // Do something that opens the camera roll

    }

}

我没有测试这段代码,但它应该与此类似。