【问题标题】:Somehow generating copy of AVPlayerItem instead accessing reference以某种方式生成 AVPlayerItem 的副本而不是访问参考
【发布时间】:2017-10-21 00:34:34
【问题描述】:

我有一个使用 AVQueuePlayer 对象的简单音频播放列表。该队列通过迭代包含自定义 UITableViewCell 对象 PlayableAudioCell 的 UITableView 来填充。这些对象有一个 AVPlayerItem 属性,audioTrack,我将它插入到 AVQueueplayer 的队列中。

我想在项目播放和完成时向这些轨道添加和删除 AVPlayerItemDidPlayToEndTime 观察者,以便我可以更新我创建的音乐播放器的标签。

由于某种原因,如果队列长于 2 个轨道,则队列中的第三个轨道不会让观察者添加到其中,因为应用它的函数传递的是轨道的副本,而不是轨道已保存到 PlayableAudioCell 对象。

我不明白这是怎么发生的,但我必须在某处创建轨道的副本,而不是引用单元格的音轨。我可以从音轨内存位置的打印语句中看出我是。

只是对我的应用程序布局的一些解释......它包含一个 tableViewController 视图,允许用户选择一个单元格并播放曲目。我还有一个 SplitViewController,它允许 FooterView 弹出并显示正在播放的曲目信息(标签、持续时间、曲目滑块)。

操作顺序:

  1. 用户在 TableView 中的单元格上按下播放键

  2. AudioQueuePlayer 的队列由按下的曲目及其下方的每个曲目填充

  3. TableViewController 的委托(FooterViewController)调用它的委托播放方法

  4. AVPlayerItemDidPlayToEndTime 观察者添加到播放的第一项

  5. 当跟踪结束时,从观察者调用选择器。在这个选择器中,当前轨道的观察者被移除,并且添加了将 AVPlayerItemDidPlayToEndTime 观察者添加到下一个轨道的代码。

当我访问单元格副本或音轨副本而不是引用 currentSelectedAudioCell 的音轨属性时,是否会弹出任何此代码?

我将在 TableViewController 中省略我的代码...我可以看出它在表格中被正确填充,问题必须在 FooterViewController 的代码中:

func play(cell: PlayableAudioCell){

    if let previousCell = currentlySelectedAudioCell, let prevFilename = currentlySelectedAudioCell?.chapter?.value(forKey: "Filename") as? String, let filename = cell.chapter?.value(forKey: "Filename") as? String{

        if filename != prevFilename{
            runningTime = 0
        }
    }

    updateWithObserver(cell: cell)

    //show footerview if it is hidden.
    if(footerView.superview?.isHidden)!{
        hideShowFooterView()
    }

    if(self.isPlaying)!{
        //print("Should pause cell")
        audioQueuePlayer?.pause()
        switchState(state: "Pause")

        playPauseRunTime(state: "Pause")

    }else{
        //print("Should play cell")
        audioQueuePlayer?.play()
        switchState(state: "Play")

        playPauseRunTime(state: "Play")
    }

    updateFooterView()
}

func updateWithObserver(cell: PlayableAudioCell){

    self.currentlySelectedAudioCell = cell
    delegate?.currentlySelectedAudioCell = cell

    let track = cell.audioTrack!

    NotificationCenter.default.addObserver(self, selector: #selector(FooterViewController.playerItemDidReachEnd(notification:)), name: Notification.Name.AVPlayerItemDidPlayToEndTime, object: track)

}

func playerItemDidReachEnd(notification: Notification){
    NotificationCenter.default.removeObserver(self, name: notification.name, object: audioQueuePlayer?.currentItem)

    if didAudioPlayEntirely(){
        recordAudioHistoryToFirebase(didFinish: true)
        if let currentlySelectedAudioCell = delegate?.currentlySelectedAudioCell{
            revealCheckMark(cell: currentlySelectedAudioCell)
        }
    }

    runningTime = 0

    //If there is just one more item in the queue, regardless of whether playAll() has been toggled...
    if (audioQueuePlayer?.items().count)! <= 1 {

        playPauseRunTime(state: "Pause")

        audioQueuePlayer?.removeAllItems()
        resetFooterViewUI()
        switchState(state: "Pause")
        hideShowFooterView()

        audioQueuePlayer?.rate = 0.0

        delegate?.currentlySelectedAudioCell = nil
        currentlySelectedAudioCell = nil
        delegate?.indexPathOfSelectedCell = nil
        indexPathOfSelectedCell = nil

    }else{

        if let indexPathOfSelectedCell = indexPathOfSelectedCell{

            playPauseRunTime(state: "Pause")
            playPauseRunTime(state: "Play")

            let row = indexPathOfSelectedCell.row + 1
            let newIndexPath = IndexPath(row: row, section: 0)
            self.indexPathOfSelectedCell = newIndexPath
            delegate?.indexPathOfSelectedCell = newIndexPath

            let newCell = self.tableView!.cellForRow(at: newIndexPath) as? PlayableAudioCell
            updateWithObserver(cell: newCell!)

            updateFooterView()
            self.tableView!.reloadData()

        }
    }
}

【问题讨论】:

    标签: ios swift nsnotificationcenter avplayeritem


    【解决方案1】:

    显然 AVQueuePlayer 每次在其队列中播放完一个项目时都会删除一个 AVPlayerItem。我的逻辑是尝试将队列的索引与 tableview 单元格数组匹配,经过几次迭代后,索引将关闭,并且观察者不会被添加到正确的播放项中。通过将 AVQueuePlayer 替换为 AVPlayer 和 AVPlayerItems 数组来修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多