我有一个集合视图,可以在每个单元格中显示视频。它还包含一个播放按钮和一个在播放视频之前显示的图像。当我向上和向下滚动它没有问题,但是当我播放视频时它显示在右侧单元格中,但有时当我向下滚动时它也会显示在另一个单元格中。我已经尝试过使用DispatchQueue(不确定它是否做正确的事情)并且这不起作用,所以我坚持不懈。我有另一个类似的集合视图,只显示图像,它工作得很好,但我有这个集合视图的问题,因为它显示视频而不是。我搜索了其他问题,但我找不到解决这个问题所需的答案。帮助非常感谢。提前致谢!
集合视图控制器
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: homePostCellId, for: indexPath) as! videoListCollectionViewCell
cell.photoImageView.sd_setImage(with: URL(string: posts[indexPath.item].imageUrl!), placeholderImage: UIImage(named: “placeholder-image.png"))
let tapGesture : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: #selector(playVideo))
return cell
}
}
集合视图单元格
class videoListCollectionViewCell: UICollectionViewCell {
var post: videoPost?
lazy var playButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
let image = UIImage(named: "playButton7")
button.tintColor = UIColor.white
button.setImage(image, for: UIControlState())
button.addTarget(self, action: #selector(handlePlay), for: .touchUpInside)
return button
}()
lazy var asset: AVURLAsset = {
let videoUrlString = self.post?.videoUrl
let url = URL(string: videoUrlString!)
var asset: AVURLAsset = AVURLAsset(url: url!)
asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
return asset
}()
var playerLayer: AVPlayerLayer?
var player: AVPlayer?
var observer:Any!
func handlePlay() {
// The video has been download already to the document directory
let filename = self.post?.postID
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(filename!)?.path
let fileManager = FileManager.default
let RealURL = NSURL(fileURLWithPath: filePath!)
if fileManager.fileExists(atPath: filePath!) {
player = AVPlayer(url: RealURL as URL)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = photoImageView.bounds
photoImageView.layer.addSublayer(playerLayer!)
player?.play()
playButton.isHidden = true
print("Playing from saved disk")
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
} else {
// The video hasn't been downloaded so it's loading from the URL
if let videoUrlString = post?.videoUrl, let url = URL(string: videoUrlString) {
player = AVPlayer(url: url)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = photoImageView.bounds
photoImageView.layer.addSublayer(playerLayer!)
player?.play()
activityIndicatorView.startAnimating()
playButton.isHidden = true
print("Attempting to play video")
self.observer = self.player?.addPeriodicTimeObserver(forInterval: CMTimeMake(1, 600), queue: DispatchQueue.main) {
[weak self] time in
if self?.player?.currentItem?.status == AVPlayerItemStatus.readyToPlay {
if (self?.player?.currentItem?.isPlaybackLikelyToKeepUp) != nil {
self?.activityIndicatorView.stopAnimating()
}
}
}
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
}
}
}
func playerDidFinishPlaying(note: NSNotification){
print("Video Stopped”)
self.player?.pause()
playButton.isHidden = false
let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality)
let filename = self.post?.postID
let documentsDirectory = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).last!
let archiveURL = documentsDirectory.appendingPathComponent(filename!)
exporter?.outputURL = archiveURL
exporter?.outputFileType = AVFileTypeMPEG4
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
let filePath = url.appendingPathComponent(filename!)?.path
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath!) {
} else {
exporter?.exportAsynchronously(completionHandler: {
print(exporter?.status.rawValue)
print(exporter?.error)
})
}
}