以下代码在为另一个 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()
}
}
为每个 cellForRowAt
创建一个新播放器,为什么?
崩溃的原因大概是这行:
player = AVPlayer(url: videoURL! as URL)
如果 player
已经存在,那么它将被释放 - 如果它有观察者(它有),它将产生崩溃。
两个建议:
1. 不要在 cellForRowAt
中创建新播放器,为您的 View Controller 创建一个全局播放器(推荐)
或
记得在创建新玩家之前移除观察者
player.removeObserver(self, forKeyPath: "status", context: nil)
player = AVPlayer(url: videoURL! as URL)
关于ios - AVPlayer 类的实例已被释放,而键值观察者仍向其注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45078417/
欢迎光临 OGeek|极客世界-中国程序员成长平台 (https://ogeek.cn/) | Powered by Discuz! X3.4 |