OGeek|极客世界-中国程序员成长平台

标题: ios - AVPlayer 类的实例已被释放,而键值观察者仍向其注册 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 18:16
标题: ios - AVPlayer 类的实例已被释放,而键值观察者仍向其注册

以下代码在为另一个 View Controller 推送 Controller 时崩溃。获取关注错误。

***** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x600000009690 of class AVPlayer was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x600000446ea0> )'**

//MARK: tableViewMethods

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return arrVideoListing.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
    //print("cell for row")
    cell = tableView.dequeueReusableCell(withIdentifier: "DashboardVideoListingCell", for: indexPath) as! DashboardVideoListingCell

    cell.lblUserName.text = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "user_name") as? String
    let videoName = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "video_title") as? String
    cell.lblHashTag.text = self.replaceChar(videoName!)

    cell.lblAddedTime.text = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "datetime") as? String
    cell.lblCategory.text = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "category") as? String

    cell.lblVotes.text = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "votes") as! String

    cell.lblDislikes.text = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "negative_votes") as! String

    cell.lblViews.text = "\((arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "views") as! String) views"

    cell.btnFullScreen.tag = indexPath.row
    cell.btnFullScreen.addTarget(self, action: #selector(fullScreenBtnClicked(_), for: .touchUpInside)


    cell.btnPlayPause.isHidden = true
    cell.imgPlay.isHidden = true


    if (selectedRow1 !=  "")
    {
        if selectedRow1 == "\(indexPath.row)" && isBtnShow == true
        {

            cell.btnPlayPause.isHidden = false
            cell.imgPlay.isHidden = false

        }
    }

    var temp: Int = getVisibleIndex()
    if temp == indexPath.row && fullvisible
    {
        cell.imgC.frame = CGRect(x: cell.playerView.frame.origin.x+5, y: cell.playerView.center.y+135, width: 20, height: 20)
        cell.imgC.image = UIImage (named: "C")

        cell.imgUserProfile.image = nil
        let imgurl1 = ((arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "user_data")as AnyObject).value(forKey: "profile_picture")as? String
        if imgurl1 == ""
        {
            cell.imgUserProfile.image = UIImage (named: "no_user_1.png")
        }
        else
        {
            let url1 = NSURL(string:imgurl1!)
            cell.imgUserProfile.imageURL = url1 as URL?
        }

            cell.btnUserInfo.tag = indexPath.row
            cell.btnUserInfo.addTarget(self, action: #selector(getUserInfoFromBtnClicked(_), for: .touchUpInside)

            let videoURL = NSURL(string: ((arrVideoListing.object(at:indexPath.row) as AnyObject).value(forKey: "url") as AnyObject) as! String)
            print(videoURL!)
            cell.playerView.isHidden = false



            player = AVPlayer(url: videoURL! as URL)

            let playerLayer = AVPlayerLayer(player: player)
            playerLayer.frame = (cell.playerView.bounds)
            playerLayer.backgroundColor = UIColor.black.cgColor
            cell.layer.addSublayer(playerLayer)
            cell.playerView?.layer.addSublayer(playerLayer)
            cell.playerView.addSubview(cell.imgC)

            activityView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
            activityView.center = cell.playerView.center
            activityView.startAnimating()
            cell.playerView.addSubview(activityView)
            addedObserver = true


            player.addObserver(self, forKeyPath: "status", options:[], context: nil)


            cell.selectionStyle = .none
            NotificationCenter.default.addObserver(self, selector: #selector(self.itemDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem)

        }
        else
        {
            cell.playerView.isHidden = true
            cell.imgThumbnail.image = nil
            let imgurl = (arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "thumbnail")as? String
            let url = NSURL(string:imgurl!)
            cell.imgThumbnail.imageURL = url as URL?

            cell.imgUserProfile.image = nil
            let imgurl1 = ((arrVideoListing.object(at: indexPath.row)as AnyObject).value(forKey: "user_data")as AnyObject).value(forKey: "profile_picture")as? String
            if imgurl1 == ""
            {
                cell.imgUserProfile.image = UIImage (named: "no_user_1.png")
            }
            else
            {
                let url1 = NSURL(string:imgurl1!)
                cell.imgUserProfile.imageURL = url1 as URL?
            }

            cell.btnPlayPause.tag = indexPath.row
            cell.btnPlayPause.addTarget(self, action: #selector(playVideoFromBtnClicked(_), for: .touchUpInside)

            cell.btnUserInfo.tag = indexPath.row
            cell.btnUserInfo.addTarget(self, action: #selector(getUserInfoFromBtnClicked(_), for: .touchUpInside)

            cell.selectionStyle = .none
            if player != nil
            {
                player.pause()
            }
            cell.backgroundColor = UIColor .blue

            return cell
       }
    return cell
}

func getVisibleIndex() -> Int
{
    for indexPath: IndexPath in tblVideoListing.indexPathsForVisibleRows!
    {
        let cellRect: CGRect = tblVideoListing.rectForRow(at: indexPath)
        let isVisible: Bool = tblVideoListing.bounds.contains(cellRect)
        if isVisible
        {
            index = Int(indexPath.row)
        }
    }
    return index
}

func scrollViewDidScroll(_ aScrollView: UIScrollView)
{

    let cells: [DashboardVideoListingCell] = tblVideoListing.visibleCells as! [DashboardVideoListingCell]
    var  a = 0
    for cell: DashboardVideoListingCell in cells
    {
        let path: IndexPath? = IndexPath(row: a, section: 0)
        index = Int((path?.row)!)
        fullvisible = true
        a  = a + 1
    }

}


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

    do {

        tblVideoListing.reloadData()

    }
    catch
    {
        print(error.localizedDescription)
    }


}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{

    if (keyPath == "status") {

        if player.status == .readyToPlay {

            player.play()
            if player.rate>=0
            {
                addedObserver = false


                if(player != nil && player.currentItem != nil)
                {

                    player.removeObserver(self, forKeyPath: "status", context: nil)
                }


                activityView.removeFromSuperview()

            }
        }
        else if player.status == .failed {

        }
    }
}


deinit
{
    if addedObserver == true
    {
        if(player != nil && player.currentItem != nil)
        {
            player.removeObserver(self, forKeyPath: "status", context: nil)

        }
    }
}

func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath)
{
    if player != nil
    {
        player.pause()
    }
}



Best Answer-推荐答案


为每个 cellForRowAt 创建一个新播放器,为什么?

崩溃的原因大概是这行:
player = AVPlayer(url: videoURL! as URL) 如果 player 已经存在,那么它将被释放 - 如果它有观察者(它有),它将产生崩溃。

两个建议:
1. 不要在 cellForRowAt 中创建新播放器,为您的 View Controller 创建一个全局播放器(推荐)

  1. 记得在创建新玩家之前移除观察者

    player.removeObserver(self, forKeyPath: "status", context: nil)
    player = AVPlayer(url: videoURL! as URL)

关于ios - AVPlayer 类的实例已被释放,而键值观察者仍向其注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45078417/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://jike.in/) Powered by Discuz! X3.4