取消分配了类AVPlayer的实例,而键值观察者仍然在其中注册

时间:2017-07-13 10:46:35

标签: ios iphone swift swift3

以下代码在pushcontroller用于另一个viewcontroller时崩溃。得到以下Erro。

  

*****由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'AVPlayer类的实例0x600000009690已被释放,而键值观察者仍在其中注册。目前的观察资料:(    上下文:0x0,属性: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()
    }
}

1 个答案:

答案 0 :(得分:0)

对于每个cellForRowAt你创建一个新玩家,为什么?

坠机的原因可能就是这一行:
player = AVPlayer(url: videoURL! as URL) 如果player已经存在,那么它将被解除分配 - 如果它有观察者(它有),它将导致崩溃。

两个建议:
1.不要在cellForRowAt中创建新的播放器,为视图控制器创建一个全局播放器(推荐)

OR

  1. 请记住在创建新播放器之前删除观察者

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