0

I have to play video in my App inside tableView cell. According to view Screen size my Table Can show 2 cell in small screen device and 3 cell in large screen device like iPhone XSMax or Xr

Flow AVPlayerController Class Created

class CustomAVPlayerViewController: AVPlayerViewController {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesBegan")
    }
}

Instances Created in cell class

var myImgArray=[String]()
    var myVideoArray=[String]()
    var myVideoPlayer : AVPlayer?
    var videoPlayerController : CustomAVPlayerViewController?
    var myPlayerItems=[AVPlayerItem]()

Prepare for Reuse Functions

override func prepareForReuse() {
        myVideoPlayer?.replaceCurrentItem(with: nil)
        videoPlayerController=nil
        myVideoPlayer=nil
        self.count=0
        myPlayerItems.removeAll()
        myImgArray.removeAll()
        myVideoArray.removeAll()
        NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
        for vieww in myScrollView.subviews {
            vieww.removeFromSuperview()
        }

    }

I am using AVPLayer instance one for a cell. A single cell can contain multiple videos so used an scrollview for that

if !videoArray.isEmpty {
            /// We've Videos
            for i in 0..<videoArray.count {
                ///Get Origin
                let xOrigin : CGFloat = CGFloat(i) * myScrollView.frame.size.width + (CGFloat(imgArray.count)*myScrollView.frame.size.width)
                let newPlayerItem = AVPlayerItem(url: URL(string: videoArray[i])!)
                myPlayerItems.append(newPlayerItem)
                if i == 0 {
                    self.myVideoPlayer=AVPlayer(playerItem: newPlayerItem)
                    self.videoPlayerController = CustomAVPlayerViewController()
                    NotificationCenter.default.removeObserver(NSNotification.Name.AVPlayerItemDidPlayToEndTime)
                    NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(note:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.myVideoPlayer!.currentItem)
                    self.videoPlayerController?.player = self.myVideoPlayer!
                    self.videoPlayerController?.view.frame = CGRect(x: xOrigin+10, y: 10, width: self.myScrollView.frame.size.width-20, height: self.myScrollView.frame.size.height-20)
                    self.myVideoPlayer?.play()
                    myScrollView.addSubview(self.videoPlayerController!.view)
                    myScrollView.bringSubviewToFront(self.videoPlayerController!.view)
                }
            }
        }

As shown In above code I am looping through Video Array and adding its subview in scrollView

Issue -

it start to lag when there are multiple cell on screen which have video or Next cell to be loaded which have video

I am using prepareForReuse to avoid High Memory Usage. App cycles unto 40 MB in run of 4 Min which include other Features too

What I can do ?

Tried Things

  1. Checking IndexPathForVisibleCell it include three cell which are displayed as soon as my cell goes off screen I remove scrollView subviews and AVPLayer instance.

  2. Using Global AVPLayer Instance but didn't worked. It doesn't play video Reason - When three cell are on screen it won't be dequeued again so Video won't be loaded as global instance will be added in one only and prepareForReuse cause no video to play

Jatin Garg
  • 86
  • 10
  • It lags because every time you scroll the video must be loaded up. I think you need to cache the videos and if you could proccess them asynchronously that would be good aswell: Check this: https://stackoverflow.com/questions/41551215/is-it-possible-to-cache-videos-ios-swift –  May 01 '19 at 14:59

1 Answers1

1

It may lag because you add and remove the AVPlayer view. Instead of removing them, you can reuse them so you can update the link when the cell is visible on screen. You can refer any article like this: Best way to check if UITableViewCell is completely visible

Hiro
  • 264
  • 3
  • 8
  • Where should I be calling this ? cellForRow isn't a good option. Can you please suggest – Jatin Garg May 02 '19 at 06:43
  • You can take a look on tableView:willDisplayCell:forRowAtIndexPath: – Hiro May 02 '19 at 08:34
  • Just a minor suggestion please. as soon I write myPlayer?.play() it cause tableview to lag very little now. Like flicker. Any idea how I can do that ? – Jatin Garg May 02 '19 at 12:22
  • You can put a delay, example after the cell appear on the screen more than one second, you will start playing. Otherwise, don't do anything. – Hiro May 03 '19 at 06:12
  • Its like using DispatchQueue.asyncAfter() ? and it that again check for visible Index ? – Jatin Garg May 03 '19 at 07:12
  • That's one of solutions. You should put a delay before playing video since user scroll very fast and they just stop when they found the right video so that's time for you to handle playing the video on the visible cell. – Hiro May 04 '19 at 16:00