AVPlayer.play() in UITableViewCell briefly blocks UI

僤鯓⒐⒋嵵緔 提交于 2019-12-03 03:42:27

Another Update Highly recommend using Facebook's Async Display Kit ASVideoNode as a drop in replacement for AVPlayer. You'll get the silky smooth Instagram tableview performance while loading and playing videos. I think AVPlayer runs a few processes on the main thread and there's no way to get around them cause it's happening at a relatively low level.

Update: Solved

I wasn't able to directly tackle the issue, but I used to some tricks and assumptions and to get the performance I wanted.

The assumption was that there's no way to avoid the video taking a certain amount of time to load on the main thread (unless you're instagram and you possess some AsyncDisplayKit magic, but I didn't want to make that jump), so instead of trying to remove the UI block, try to hide it instead.

I hid the UIBlock by implementing a simple isScrolling check on on my tableView

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    if(self.isScrolling){
        if(!decelerate){
            self.isScrolling = false
            self.tableView.reloadData()
        }
    }
}

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {

    if(self.isScrolling){
        self.isScrolling = false
        self.tableView.reloadData()
    }
}

func scrollViewWillBeginDragging(scrollView: UIScrollView) {
    self.isScrolling = true
}

And then just made sure not to load the video cells when tableView is scrolling or a video is already playing, and reload the the tableView when the scrolling stops.

if(!isScrolling && cell.videoPlayer == nil){

    //Load video cell here
}

But make sure to remove the videoPlayer, and stop listening to replay notifications once the videoCell is not on the screen anymore.

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    if(tableView.indexPathsForVisibleRows?.indexOf(indexPath) == nil){

        if (cell.videoPlayer != nil && murmur.video_url != nil){

            if(cell.videoPlayer.rate != 0){

                cell.videoPlayer.removeObserver(cell, forKeyPath: "status")
                cell.videoPlayer = nil;
                cell.videoPlayerController.view.alpha = 0;
            }
        }
    }
}

With these changes I was able to achieve a smooth UI with multiple (2) video cells on the screen at a time. Hope this helps and let me know if you have any specific questions or if what I described wasn't clear.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!