I tested the demo for video only,
Here's how you can achieve this - Create your own cell class to keep watching a video player and also handle playback and pause methods for avplayer itself.
This is my Custom Cell class -
import UIKit
import AVFoundation
class VideoCellTableViewCell: UITableViewCell {
@IBOutlet weak var videoPlayerSuperView: UIView!
var avPlayer: AVPlayer?
var avPlayerLayer: AVPlayerLayer?
var paused: Bool = false
var videoPlayerItem: AVPlayerItem? = nil {
didSet {
avPlayer?.replaceCurrentItem(with: self.videoPlayerItem)
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.setupMoviePlayer()
}
func setupMoviePlayer(){
self.avPlayer = AVPlayer.init(playerItem: self.videoPlayerItem)
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer?.videoGravity = AVLayerVideoGravityResizeAspect
avPlayer?.volume = 3
avPlayer?.actionAtItemEnd = .none
if UIScreen.main.bounds.width == 375 {
let widthRequired = self.frame.size.width - 20
avPlayerLayer?.frame = CGRect.init(x: 0, y: 0, width: widthRequired, height: widthRequired/1.78)
}else if UIScreen.main.bounds.width == 320 {
avPlayerLayer?.frame = CGRect.init(x: 0, y: 0, width: (self.frame.size.height - 120) * 1.78, height: self.frame.size.height - 120)
}else{
let widthRequired = self.frame.size.width
avPlayerLayer?.frame = CGRect.init(x: 0, y: 0, width: widthRequired, height: widthRequired/1.78)
}
self.backgroundColor = .clear
self.videoPlayerSuperView.layer.insertSublayer(avPlayerLayer!, at: 0)
NotificationCenter.default.addObserver(self,
selector: #selector(self.playerItemDidReachEnd(notification:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: avPlayer?.currentItem)
}
func stopPlayback(){
self.avPlayer?.pause()
}
func startPlayback(){
self.avPlayer?.play()
}
func playerItemDidReachEnd(notification: Notification) {
let p: AVPlayerItem = notification.object as! AVPlayerItem
p.seek(to: kCMTimeZero)
}
}
-
AVFoundation Framework
import UIKit
import AVFoundation
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var aboutToBecomeInvisibleCell = -1
var avPlayerLayer: AVPlayerLayer!
var videoURLs = Array<URL>()
var firstLoad = true
@IBOutlet weak var feedTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
feedTableView.delegate = self
feedTableView.dataSource = self
for i in 0..<2{
let url = Bundle.main.url(forResource:"\(i+1)", withExtension: "mp4")
videoURLs.append(url!)
}
visibleIP = IndexPath.init(row: 0, section: 0)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 290
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0
}
URL- cellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.feedTableView.dequeueReusableCell(withIdentifier: "videoCell") as! VideoCellTableViewCell
cell.videoPlayerItem = AVPlayerItem.init(url: videoURLs[indexPath.row % 2])
return cell
}
, ,
visible IndexPath, tablecell.
visibleCells, , , , .
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let indexPaths = self.feedTableView.indexPathsForVisibleRows
var cells = [Any]()
for ip in indexPaths!{
if let videoCell = self.feedTableView.cellForRow(at: ip) as? VideoCellTableViewCell{
cells.append(videoCell)
}
}
let cellCount = cells.count
if cellCount == 0 {return}
if cellCount == 1{
if visibleIP != indexPaths?[0]{
visibleIP = indexPaths?[0]
}
if let videoCell = cells.last! as? VideoCellTableViewCell{
self.playVideoOnTheCell(cell: videoCell, indexPath: (indexPaths?.last)!)
}
}
if cellCount >= 2 {
for i in 0..<cellCount{
let cellRect = self.feedTableView.rectForRow(at: (indexPaths?[i])!)
let intersect = cellRect.intersection(self.feedTableView.bounds)
let currentHeight = intersect.height
print("\n \(currentHeight)")
let cellHeight = (cells[i] as AnyObject).frame.size.height
if currentHeight > (cellHeight * 0.95){
if visibleIP != indexPaths?[i]{
visibleIP = indexPaths?[i]
print ("visible = \(indexPaths?[i])")
if let videoCell = cells[i] as? VideoCellTableViewCell{
self.playVideoOnTheCell(cell: videoCell, indexPath: (indexPaths?[i])!)
}
}
}
else{
if aboutToBecomeInvisibleCell != indexPaths?[i].row{
aboutToBecomeInvisibleCell = (indexPaths?[i].row)!
if let videoCell = cells[i] as? VideoCellTableViewCell{
self.stopPlayBack(cell: videoCell, indexPath: (indexPaths?[i])!)
}
}
}
}
}
}
.
func playVideoOnTheCell(cell : VideoCellTableViewCell, indexPath : IndexPath){
cell.startPlayback()
}
func stopPlayBack(cell : VideoCellTableViewCell, indexPath : IndexPath){
cell.stopPlayback()
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
print("end = \(indexPath)")
if let videoCell = cell as? VideoCellTableViewCell {
videoCell.stopPlayback()
}
}
}
,