如何在不同的 UICollectionView 单元格中显示不同的视频?

Posted

技术标签:

【中文标题】如何在不同的 UICollectionView 单元格中显示不同的视频?【英文标题】:How to show different videos in different UICollectionView cells? 【发布时间】:2019-12-06 21:57:05 【问题描述】:

我试图在五个不同的 UICollectionView 单元格中显示 5 个不同的视频。这听起来很容易做到,并且使用 3 个单元格它工作正常,但现在不知何故所有视频都在错误的单元格中。

这是一个丑陋的解决方案,但它以前有效,我想不出任何其他解决方案。

这是 AVPlayer 和 AVPlayerLayer 的五个不同实例。

    let theURL = Bundle.main.url(forResource:"summer", withExtension: "mp4")
    let theURL2 = Bundle.main.url(forResource:"newyork", withExtension: "mp4")
    let theURL3 = Bundle.main.url(forResource:"amber", withExtension: "mp4")
    let theURL4 = Bundle.main.url(forResource:"luckywhite", withExtension: "mp4")
    let theURL5 = Bundle.main.url(forResource:"coconut", withExtension: "mp4")
    avPlayer = AVPlayer(url: theURL!)
    avPlayerLayer = AVPlayerLayer(player: avPlayer)
    avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
    avPlayer.volume = 0
    avPlayer.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(self,
    selector: #selector(playerItemDidReachEnd(notification:)),
    name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
    object: avPlayer.currentItem)


    avPlayer2 = AVPlayer(url: theURL2!)
    avPlayerLayer2 = AVPlayerLayer(player: avPlayer2)
    avPlayerLayer2.videoGravity = AVLayerVideoGravity.resizeAspectFill
    avPlayer2.volume = 0
    avPlayer2.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(self,
    selector: #selector(playerItemDidReachEnd(notification:)),
    name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
    object: avPlayer2.currentItem)


    avPlayer3 = AVPlayer(url: theURL3!)
    avPlayerLayer3 = AVPlayerLayer(player: avPlayer3)
    avPlayerLayer3.videoGravity = AVLayerVideoGravity.resizeAspectFill
    avPlayer3.volume = 0
    avPlayer3.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(self,
    selector: #selector(playerItemDidReachEnd(notification:)),
    name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
    object: avPlayer3.currentItem)

    avPlayer4 = AVPlayer(url: theURL4!)
    avPlayerLayer4 = AVPlayerLayer(player: avPlayer4)
    avPlayerLayer4.videoGravity = AVLayerVideoGravity.resizeAspectFill
    avPlayer4.volume = 0
    avPlayer4.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(self,
    selector: #selector(playerItemDidReachEnd(notification:)),
    name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
    object: avPlayer4.currentItem)

    avPlayer5 = AVPlayer(url: theURL5!)
    avPlayerLayer5 = AVPlayerLayer(player: avPlayer5)
    avPlayerLayer5.videoGravity = AVLayerVideoGravity.resizeAspectFill
    avPlayer5.volume = 0
    avPlayer5.actionAtItemEnd = .none
    NotificationCenter.default.addObserver(self,
    selector: #selector(playerItemDidReachEnd(notification:)),
    name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
    object: avPlayer5.currentItem)

我在这里将视频放入单元格中。

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell

    switch indexPath.item 
        case 0:
            self.avPlayerLayer.frame = cell.image.layer.bounds
            cell.image.layer.insertSublayer(self.avPlayerLayer, at: 0)

        case 1:
            self.avPlayerLayer2.frame = cell.image.layer.bounds
            cell.image.layer.insertSublayer(self.avPlayerLayer2, at: 0)

        case 2:
            self.avPlayerLayer3.frame = cell.image.layer.bounds
            cell.image.layer.insertSublayer(self.avPlayerLayer3, at: 0)

        case 3:
            self.avPlayerLayer4.frame = cell.image.layer.bounds
            cell.image.layer.insertSublayer(self.avPlayerLayer4, at: 0)

        default:
            self.avPlayerLayer5.frame = cell.image.layer.bounds
            cell.image.layer.insertSublayer(self.avPlayerLayer5, at: 0)
    

为什么它不能正常工作?我认为在使用 indexPaths 时我做的一切都是正确的。

【问题讨论】:

【参考方案1】:

细胞被重复使用,当你这样做时

 self.avPlayerLayer4.frame = cell.image.layer.bounds
 cell.image.layer.insertSublayer(self.avPlayerLayer4, at: 0)

所以考虑在插入之前清洁它

  cell.image.layer.sublayers?.forEach 
      if $0 is AVPlayerLayer 
          $0.removeFromSuperlayer()
      
   

它最多添加层并显示之前添加的旧层,而不是重复的代码,您需要编写一个从 url 返回层并添加它的函数


还可以考虑使用类似的数组

var arr = [URL]()

用它代替开关

【讨论】:

有什么解决方案可以让它发挥作用吗?还是不可能? 它的工作就像魅力一样。我希望它适用于 10-15 个不同的视频。非常感谢您,先生!

以上是关于如何在不同的 UICollectionView 单元格中显示不同的视频?的主要内容,如果未能解决你的问题,请参考以下文章

当用户滚动到不同的页面时,如何在“UICollectionView”的不同背景颜色之间淡化?

UiCollectionview 允许对特定单元格进行单选

如何将 Plist 文件与 UITableView / UICollectionView 一起使用?

如何 UICollectionView 每列具有不同的行

设置单元格数据后如何更新 UICollectionView 中单元格的大小?

UICollectionview 中的不同单元格大小