【问题标题】:Collection view with segment duplicate cells带有段重复单元格的集合视图
【发布时间】:2017-01-28 03:45:27
【问题描述】:

当我将集合视图与 segmentView 一起使用时遇到问题。

我有一个viewController,它有一个 segmentView,其中包含 4 个元素 (0 => 全部、1 => 照片、2 => 音频、3 => 视频) 这是和示例:

我有一个 collectionView 来显示数据,具体取决于从 segmentController 中点击的类别

它正在工作并显示数据,这是我的 collectionView 显示数据的方法

 // MARK: Datasource collection method

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

        if segmentStatues == 0
        {
            let cellForAll = collectionView.dequeueReusableCell(withReuseIdentifier: "AllItemsCell", for: indexPath) as! AllItemsCollectionViewCell

            // reset elements before declare

            cellForAll.cellImage.image = nil
            cellForAll.playBtn.isHidden = true

            cellForAll.layer.borderWidth = 1
            cellForAll.layer.borderColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0).cgColor
            // When type is an image
            if sociaPosts[(indexPath as NSIndexPath).row].postType == "image"
            {

                cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].postUrl))


            }else if sociaPosts[(indexPath as NSIndexPath).row].postType == "audio"
            {

                cellForAll.cellImage.image  = UIImage(named: "recorde_icon")


            }else if sociaPosts[(indexPath as NSIndexPath).row].postType == "video"
            {
                cellForAll.cellImage.sd_setImage(with: URL(string: sociaPosts[(indexPath as NSIndexPath).row].thumbURL))
                cellForAll.playBtn.isHidden = false
            }

            return cellForAll

        }else{

            // Cell if Images or videos or audios

            let newCell = collectionView.dequeueReusableCell(withReuseIdentifier: "beepbeep", for: indexPath) as! userProfileImageCollectionViewCell

            // If the type is images

            if  segmentStatues == 1
            {   
                // Set image URL

                newCell.cellImage.sd_setImage(with: URL(string: imagesPosts[(indexPath as NSIndexPath).row].postUrl))

                // Get image likes and comments and shares

                newCell.likeCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].likes_count)
                newCell.commentCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].comments_count)
                newCell.shareCount.text = String(imagesPosts[(indexPath as NSIndexPath).row].shares_count)

            } else if segmentStatues == 3
            {
                // For Video player

             var player = newCell.customVid
            player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer

           player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts[indexPath.row].postUrl , videoThumbnail: URL(string: videosPosts[indexPath.row].thumbURL), onReady: nil)
                // Set video URL and Thumbnail

                // Get video likes and comments and shares
                newCell.likeCount.text = String(videosPosts[(indexPath as NSIndexPath).row].likes_count)
                newCell.commentCount.text = String(videosPosts[(indexPath as NSIndexPath).row].comments_count)
                newCell.shareCount.text = String(videosPosts[(indexPath as NSIndexPath).row].shares_count)

            }else if segmentStatues == 2
            {
                // Audio player
                let ad = Bundle.main.loadNibNamed("AudioPlayerView", owner: self, options: nil)?.last as! AudioPlayerView
                ad.frame = CGRect(x: (newCell.contentView.frame.size.width - newCell.contentView.frame.size.height * 0.6) / 2, y: 20 , width: newCell.contentView.frame.size.height * 0.6, height: newCell.contentView.frame.size.height * 0.6)
                ad.playImageView.image = nil

                ad.tag = 6666

                newCell.contentView.addSubview(ad)

                // Set audio URL
                ad.audioPath = URL(string: audiosPosts[indexPath.row].postUrl)
                ad.viewInitialization()

                // Get Audio  likes and comments and shares
                newCell.likeCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].likes_count)
                newCell.commentCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].comments_count)
                newCell.shareCount.text = String(audiosPosts[(indexPath as NSIndexPath).row].shares_count)   

            }
            return newCell
        } 
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

        if self.segmentStatues == 0
        {

            return  sociaPosts.count
        }else if self.segmentStatues == 1
        {
            return imagesPosts.count
        }else if self.segmentStatues == 2
        {
            return audiosPosts.count
        }else
        {
            return videosPosts.count
        }
    }

我的收藏视图中有 2 个自定义单元格,一个用于所有项目,另一个用于(图像-音频-视频)视图

我的问题是数据正在显示,但是当我在 userProfileImageCollectionViewCell

中的段之间更改时,单元格重复

这两张图说明问题

单击音频段时显示所有音频单元格

但是当我点击像这样复制的图像或视频片段单元格后

仅在音频 - 图像 - 视频中发生**(userProfileImageCollectionViewCell)**

最后是我的 userProfileImageCollectionViewCell 代码:

更新:

import UIKit
import SDWebImage
class userProfileImageCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var customVid: videoPlayer!
    @IBOutlet weak var cellImage: UIImageView!

    @IBOutlet weak var likeButton: UIButton!

    @IBOutlet weak var likeCount: UILabel!
    @IBOutlet weak var commentButton: UIButton!

    @IBOutlet weak var commentCount: UILabel!
    @IBOutlet weak var shareButton: UIButton!
    @IBOutlet weak var shareCount: UILabel!

    override func prepareForReuse() {
        cellImage.sd_setImage(with: nil)
       self.customVid.subviews.forEach({ $0.removeFromSuperview() })

    }
}

【问题讨论】:

  • In userProfileImageCollectionViewCell in prepareForReuse() 重置所有值(尤其是在一种情况下可能存在但在另一种情况下不存在的值)。否则,您可以在tableView:cellForRowAtIndexPath() 执行此操作,但由于您的单元格有一个自定义文件,我建议您在prepareForReuse() 执行此操作。
  • segmentedController 操作中的collectionView.reloadData() 应该对您有所帮助。
  • 最后一个条件只使用else 而不是else if segmentStatues == 2
  • @Larme 如何重置我的数据?特别是音频和视频?
  • 单元格被重复使用,所以问题是您在视频的情况下添加子视图:newCell.contentView.addSubview(player) 为其添加视图,然后将其删除。如果您滚动很多并使用 3D Hierarchy Debug,您会看到其中有几个在彼此之上。

标签: ios swift uicollectionview uisegmentedcontrol


【解决方案1】:

问题是UICollectionViewCell(顺便说一下UITableViewCell)被重用了。

简单地说: 当滚动时单元格从屏幕上消失时,它可能会回到顶部/底部(根据滚动方向)。但这不是一个新的“干净”细胞,它是以前的细胞。这就是复用系统。

所以,当你这样做时:newCell.contentView.addSubview(ad) 你每次都添加一个新的子视图,而不检查是否已经有一个。刚刚打桩的子视图。使用3D Hierarchy Debug of XCode 很容易检查。

由于您有一个userProfileImageCollectionViewCell 文件,因此最好的解决方案是使用prepareForReuse()。 创建一个IBOutlet(我们称之为customVid),它将添加广告/播放器作为其子视图。 在prepareForReuse() 中删除customVid 的所有子视图。 在collectionView:cellForRowAtIndexPath:,做这样的事情:

var player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer 
player?.newIntitVideoPlayer(forViewController: self, videoURL: videosPosts 
newCell.customVid.addSubview(player)

ad 复制相同的机制(您可以使用相同的子视图,这取决于您)。

现在,一些与您的问题无关的建议:

以大写开头的类命名:userProfileImageCollectionViewCell => UserProfileImageCollectionViewCell

我会在userProfileImageCollectionViewCell 中创建方法以使您的代码更具可读性。我不会说 Swift,所以我的下一行代码可能无法编译,但你应该明白了:

func fillWithVideo(videoParam video: CustomVideoClass) {
     var player = newCell.customVid
     player = Bundle.main.loadNibNamed("VieoPlayer", owner: self, options: nil)?.last as? videoPlayer
     player?.newIntitVideoPlayer(forViewController: NOTself, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)
    self.customVid.addSubview(player)
    // Set video URL and Thumbnail

    // Get video likes and comments and shares
     self.likeCount.text = String(video.likes_count)
     self.commentCount.text = String(video.comments_count)
     self.shareCount.text = String(video.shares_count)
}

collectionView:cellForRowAtIndexPath:

//If it's the correct section
let video = videosPosts[(indexPath as NSIndexPath).row] as CustomVideoClass
cell fillWithVideo(video)

请注意,您似乎使用了UIViewController,因此您可能希望添加 UIViewController 参数以使newIntitVideoPlayer() 方法起作用,但我不想将其放在前面的示例中让它更简单。您可能需要替换以下行:

cell fillWithVideo(video andViewController:self)

func fillWithVideo(videoParam video: CustomVideoClass andViewController viewController: UIViewController)
player?.newIntitVideoPlayer(forViewController: viewController, videoURL: video.postUrl, videoThumbnail: URL(string: video.thumbURL), onReady: nil)

等等。对于每个部分的特定部分。它使阅读您正在做的事情变得更容易。仅在collectionView:cellForRowAtIndexPath: 中处理逻辑(哪个部分应该获取哪个项目等),其余的处理到可能适应的单元格。

【讨论】:

  • 非常感谢您的回答和解释:))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多