当 UICollectionViewCell 不在视图中时尝试暂停视频
Trying to pause video when the UICollectionViewCell is out of view
我正在使用从 Firebase 加载的 URL 填充集合视图。但是当我退出视图或向上滚动集合视图时,我无法让视频暂停。当我使用导航控制器返回时,我仍然可以听到后台播放的视频。然后当我再次进入视图时,视频开始播放,但第一个没有播放完。
这是我的视图控制器。有小费吗?谢谢你!我对 Swift 还是个新手,所以请原谅我的无知。
import UIKit
import AVKit
import AVFoundation
import Firebase
import FirebaseDatabase
import SDWebImage
class ComedyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var avPlayer = AVPlayer()
var avPlayerLayer = AVPlayerLayer()
@IBOutlet weak var comedyCollectionView: UICollectionView!
var comedyVideoArray = [ComedyModel]()
var comedyDBRef: DatabaseReference! {
return Database.database().reference().child("comedy")
}
override func viewDidLoad() {
super.viewDidLoad()
loadComedyDB()
}
func loadComedyDB() {
comedyDBRef.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
self.comedyVideoArray.removeAll()
for comedyData in snapshot.children.allObjects as! [DataSnapshot] {
let comedyObject = comedyData.value as? [String: AnyObject]
let comedyPostTitle = comedyObject?["title"]
let comedyPostDescription = comedyObject?["description"]
let comedyArticleLink = comedyObject?["link"]
let comedyVideoUrl = comedyObject?["url"]
let allComedyData = ComedyModel(title: comedyPostTitle as! String?, description: comedyPostDescription as! String?, link: comedyArticleLink as! String?, url: comedyVideoUrl as! String?)
self.comedyVideoArray.append(allComedyData)
self.comedyCollectionView.reloadData()
}
}
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(comedyVideoArray.count)
return comedyVideoArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellB = comedyCollectionView.dequeueReusableCell(withReuseIdentifier: "comedyCell", for: indexPath) as! ComedyCollectionViewCell
let data = comedyVideoArray[indexPath.row]
let item = AVPlayerItem(url: URL(string: data.url!)!)
self.avPlayer = AVPlayer(playerItem: item)
self.avPlayer.actionAtItemEnd = .none
self.avPlayerLayer = AVPlayerLayer(player: self.avPlayer)
self.avPlayerLayer.videoGravity = .resizeAspectFill
self.avPlayerLayer.frame = CGRect(x: 0, y: 0, width: cellB.frame.size.width, height: cellB.frame.size.height / 2)
cellB.videoView.layer.addSublayer(self.avPlayerLayer)
self.avPlayer.play()
//cellB.videoView.sd_setImage(with: URL(string: data.link!), placeholderImage: UIImage(named: "1"))
return cellB
}
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if collectionView == self.comedyCollectionView {
self.avPlayer.pause()
}
}
}
有几个问题:
UICollectionView
在显示新单元格之前调用 cellForItemAt
,这意味着旧单元格仍然可见。现在,当您使新单元格出列时,您正在将指针 avPlayer
更改为 AVPlayer
的新实例,这样当您暂停视频时,您实际上是在新单元格上调用 pause()
视频。旧的继续播放(在当时仍然可见的单元格中)。
每次 UICollectionView
调用 cellForItemAt
时,您都会将 AVPlayer
的实例添加到单元格中。但是 UICollectionView
尝试重用那些不再可见的单元格,因此您最终会在每个单元格中得到很多 AVPlayer
。为避免这种情况,您应该查看如何在单元格上使用 prepareForReuse
方法。我还建议您在单元格本身中创建 AVPlayer
(通过子类化 UICollectionViewCell
),然后在 cellForItemAt
方法中设置它的 playerItem
。这样你就可以在你的 didEndDisplaying
方法中暂停当前播放的视频,就像这样(只是一个例子):
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if let comedyCell = cell as? ComedyCollectionViewCell {
comedyCell.avPlayer.pause()
}
}
我正在使用从 Firebase 加载的 URL 填充集合视图。但是当我退出视图或向上滚动集合视图时,我无法让视频暂停。当我使用导航控制器返回时,我仍然可以听到后台播放的视频。然后当我再次进入视图时,视频开始播放,但第一个没有播放完。
这是我的视图控制器。有小费吗?谢谢你!我对 Swift 还是个新手,所以请原谅我的无知。
import UIKit
import AVKit
import AVFoundation
import Firebase
import FirebaseDatabase
import SDWebImage
class ComedyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var avPlayer = AVPlayer()
var avPlayerLayer = AVPlayerLayer()
@IBOutlet weak var comedyCollectionView: UICollectionView!
var comedyVideoArray = [ComedyModel]()
var comedyDBRef: DatabaseReference! {
return Database.database().reference().child("comedy")
}
override func viewDidLoad() {
super.viewDidLoad()
loadComedyDB()
}
func loadComedyDB() {
comedyDBRef.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
self.comedyVideoArray.removeAll()
for comedyData in snapshot.children.allObjects as! [DataSnapshot] {
let comedyObject = comedyData.value as? [String: AnyObject]
let comedyPostTitle = comedyObject?["title"]
let comedyPostDescription = comedyObject?["description"]
let comedyArticleLink = comedyObject?["link"]
let comedyVideoUrl = comedyObject?["url"]
let allComedyData = ComedyModel(title: comedyPostTitle as! String?, description: comedyPostDescription as! String?, link: comedyArticleLink as! String?, url: comedyVideoUrl as! String?)
self.comedyVideoArray.append(allComedyData)
self.comedyCollectionView.reloadData()
}
}
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(comedyVideoArray.count)
return comedyVideoArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cellB = comedyCollectionView.dequeueReusableCell(withReuseIdentifier: "comedyCell", for: indexPath) as! ComedyCollectionViewCell
let data = comedyVideoArray[indexPath.row]
let item = AVPlayerItem(url: URL(string: data.url!)!)
self.avPlayer = AVPlayer(playerItem: item)
self.avPlayer.actionAtItemEnd = .none
self.avPlayerLayer = AVPlayerLayer(player: self.avPlayer)
self.avPlayerLayer.videoGravity = .resizeAspectFill
self.avPlayerLayer.frame = CGRect(x: 0, y: 0, width: cellB.frame.size.width, height: cellB.frame.size.height / 2)
cellB.videoView.layer.addSublayer(self.avPlayerLayer)
self.avPlayer.play()
//cellB.videoView.sd_setImage(with: URL(string: data.link!), placeholderImage: UIImage(named: "1"))
return cellB
}
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if collectionView == self.comedyCollectionView {
self.avPlayer.pause()
}
}
}
有几个问题:
UICollectionView
在显示新单元格之前调用cellForItemAt
,这意味着旧单元格仍然可见。现在,当您使新单元格出列时,您正在将指针avPlayer
更改为AVPlayer
的新实例,这样当您暂停视频时,您实际上是在新单元格上调用pause()
视频。旧的继续播放(在当时仍然可见的单元格中)。每次
UICollectionView
调用cellForItemAt
时,您都会将AVPlayer
的实例添加到单元格中。但是UICollectionView
尝试重用那些不再可见的单元格,因此您最终会在每个单元格中得到很多AVPlayer
。为避免这种情况,您应该查看如何在单元格上使用prepareForReuse
方法。我还建议您在单元格本身中创建AVPlayer
(通过子类化UICollectionViewCell
),然后在cellForItemAt
方法中设置它的playerItem
。这样你就可以在你的didEndDisplaying
方法中暂停当前播放的视频,就像这样(只是一个例子):func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { if let comedyCell = cell as? ComedyCollectionViewCell { comedyCell.avPlayer.pause() } }