停止在 UITableView 的嵌套 UICollectionView 中播放视频或仅在嵌套结构中的可见单元格上播放
Posted
技术标签:
【中文标题】停止在 UITableView 的嵌套 UICollectionView 中播放视频或仅在嵌套结构中的可见单元格上播放【英文标题】:Stop playing video in nested UICollectionView in UITableView or Play only on the visible cell in nested structure 【发布时间】:2020-12-02 13:48:26 【问题描述】:我已经为一个问题苦苦挣扎了很多天。我正在使用嵌套结构来显示多张照片和视频,例如 Instagram 提要。但问题是,当我启动 viewController 时,它开始播放视频并且在滚动时不会停止播放视频。如何仅播放嵌套结构中可见单元格的视频并停止所有其他视频?
在这里简单解释一下我的结构, UIViewController -> UITableView -> UITableViewCell -> UICollectioinView -> UICollectionViewCell -> section = 0(对于照片数组)+ section = 1(对于多个视频)。
extension HomeVC: UITableViewDelegate, UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
postsArray.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "HomeTVC", for: indexPath) as! HomeTVC
let objPost = postsArray[indexPath.row]
cell.postImagesArray = []
cell.postImagesArray = objPost.images ?? [Images].init()
cell.videos = []
cell.videos = objPost.videos ?? []
return cell
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
guard let tableViewCell = cell as? HomeTVC else return
tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)
UICollectionView 委托方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCVC", for: indexPath) as! HomeCVC
if indexPath.section == 0
let images = postsArray[collectionView.tag].images?[indexPath.row]
let imagePath = APIConstants.BasePathImage + (images?.post_merge_image ?? "")
cell.imgPropertyView.sd_setImage(with: URL(string: imagePath), placeholderImage: UIImage(named: "placeholder"))
return cell
else
let videos = postsArray[collectionView.tag].videos?[indexPath.row]
cell.videoView.isHidden = false
let videoUrl = APIConstants.BasePathImage + (videos?.post_video ?? "")
cell.playVideo(videoUrl)
return cell
func collectionView(_ collectionView: UICollectionView,
didEndDisplaying cell:
UICollectionViewCell, forItemAt indexPath: IndexPath)
guard let cell = cell as? HomeCVC else return
cell.stopVideo()
【问题讨论】:
为什么你的didEndDisplaying
方法在cellForItemAt
里面?
您能帮我解决问题吗?
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
在UICollectionViewDelegate
中定义,因此您应该确保将委托以及数据源设置为您的tableViewCell,例如collectionView.dataSource = self
和collectionView.delegate = self
,在这样做之后didEndDisplaying
你的 tableViewCell 中的方法将被调用,你的逻辑应该工作
【参考方案1】:
因此,在为此困扰了很多天并付出了很多努力之后,我自己解决了这个问题。我会在这里为你们发布答案。
了解结构
UITableView > UITableViewCell > UICollectionView > UICollectionViewCell > MultipleSections > VideoLayer > 播放/暂停(对于可见单元格)
解决方案 - Swift 5
您将使用外部 UITableView 的 WillDisplay 方法将标签分配给内部 UICollectionView,并将类似地分配 cellForRowat 中的数据。所以在 UICollectionView DataSource/Delegates 中,你会用到这些方法。
CollectionView cellForItemAt 方法
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCVC", for: indexPath) as! HomeCVC
let images = postsArray[collectionView.tag].images?[indexPath.row]
if indexPath.section == 0 //if multiple sections for image and videos
let imagePath = APIConstants.BasePathImage + (images?.post_merge_image ?? "")
cell.imgPropertyView.sd_setImage(with: URL(string: imagePath), placeholderImage: UIImage(named: "placeholder"))
return cell
else
let videos = postsArray[collectionView.tag].videos?[indexPath.row]
cell.videoView.isHidden = false
let videoUrl = APIConstants.BasePathImage + (videos?.post_video ?? "") //your video Url
cell.playVideo(videoUrl: videoUrl) // to load the video here and will play in willDisplay
return cell
//
CollectionView didEndDisplaying 方法
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
if let homeCVC = cell as? HomeCVC
homeCVC.stopVideo()
print("Playing Stopped:")
CollectionView willDisplay 方法
您将加载 UICollectionView 的 cellForItemAt 方法,并仅在可见单元格分别位于视图边界和超出视图边界时使用这些方法播放和停止视频。
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
if let homeCVC = cell as? HomeCVC
if indexPath.section == 1
homeCVC.player.play()
print("Playing Started:")
【讨论】:
以上是关于停止在 UITableView 的嵌套 UICollectionView 中播放视频或仅在嵌套结构中的可见单元格上播放的主要内容,如果未能解决你的问题,请参考以下文章
在 UIScrollView 中快速嵌套 UITableView