简体   繁体   中英

UICollectionView CustomCell ReUse

I am fetching user's Photo Asset and trying to create a custom UICollectionViewCell in my UICollectionView where the first index is a Camera Image and other cells are the Camera Images. But when I scroll, it's like the image at the index is recreated and I notice some images in my cell get the view I added at the 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
}

Below is an image for illustration 错误的后继

Reusable cells are reused by the collection view when they are scrolled outside the view to prevent a lot of memory use. When a certain cell gets scrolled outside of the view the collection view will mark them as reusable. Reusable cells will be reused by the collection view instead of creating new ones. This will significantly reduce memory use. Why would you keep 1000 cells in memory if only 20 of them fit on the screen at the same time.

because cells are reused, they will still contain the content of previous cell, this means that the cell still has the cameraButton as a subview. Same story with the images, you need to manually remove them at from the cell and make sure al old content gets replaced or removed.

When you perform methods that will download and set the image to the cell after a while, the cell could still contain the image of the previous cell. You should clear the image at the beginning of the cellForRowAtIndexPath method to remove the old image/subviews.

See example below:

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

    }

}

I didn't test this code, but it should be something similar to this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM