Swift 5: AVPlayer накладывает несколько аудиофайлов друг на друга - PullRequest
0 голосов
/ 27 мая 2020

Я создаю приложение Swift 5 musi c, в котором таблица загружает и перечисляет несколько объектов из JSON API. После щелчка по записи навигатор вызывает подробное представление для выбранного элемента.

Ниже вы можете увидеть мой контроллер подробного представления, называемый BroadcastDetailViewController. Как видите, есть playBroadcastButton, который воспроизводит аудиофайл и настраивает AVAudioSession.

Пока все хорошо. Но после того, как я реализовал возможность прокрутки аудиофайла через ползунок центра управления (commandCenter.changePlaybackPositionCommand.addTarget) и go обратно к моему контроллеру табличного представления и выбора другого элемента для воспроизведения его аудиофайла, AVPlayer накладывает несколько аудиофайлов на друг друга и воспроизводит их одновременно. Я не хочу такого поведения. До того, как я реализовал кнопки управления, весь процесс замены аудиофайлов работал нормально.

У меня вопрос, почему проигрыватель внезапно воспроизводит другой файл поверх другого вместо того, чтобы приглушить / приглушить старый и заменить это с новым?

class BroadcastDetailViewController: UIViewController {

    var player = AVPlayer()
    var playerItem: AVPlayerItem!

    var broadcast:Broadcasts?

    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!

    @IBAction func playBroadcastButton(_ sender: Any) {
        player.play()
        setupAVAudioSession()
    }

    private func setupAVAudioSession() {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
            try AVAudioSession.sharedInstance().setActive(true)
            debugPrint("AVAudioSession is Active and Category Playback is set")
            UIApplication.shared.beginReceivingRemoteControlEvents()
            setupCommandCenter()
        } catch {
            debugPrint("Error: \(error)")
        }
    }

    private func setupCommandCenter() {

        // Meta
        var nowPlayingInfo = [String : Any]()

        nowPlayingInfo[MPMediaItemPropertyTitle] = broadcast?.title ?? "Radio Bass"
        nowPlayingInfo[MPMediaItemPropertyArtist] = "Radio Bass"
        nowPlayingInfo[MPMediaItemPropertyAlbumTitle] = "Radio Bass."
        nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = playerItem.currentTime().seconds
        nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = playerItem.asset.duration.seconds
        nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = player.rate

        MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo

        let commandCenter = MPRemoteCommandCenter.shared()
        commandCenter.playCommand.isEnabled = true
        commandCenter.pauseCommand.isEnabled = true
        commandCenter.playCommand.addTarget { [weak self] (event) -> MPRemoteCommandHandlerStatus in
            self?.player.play()
            return .success
        }
        commandCenter.pauseCommand.addTarget { [weak self] (event) -> MPRemoteCommandHandlerStatus in
            self?.player.pause()
            return .success
        }

        // Scrubber
        commandCenter.changePlaybackPositionCommand.addTarget { event in
            let seconds = (event as? MPChangePlaybackPositionCommandEvent)?.positionTime ?? 0
            let time = CMTime(seconds: seconds, preferredTimescale: 1)
            self.player.seek(to: time)
            return .success
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let urlAudioString = broadcast?.audio

        playerItem = AVPlayerItem(url: URL(string: urlAudioString!)!)
        player = AVPlayer(playerItem: playerItem)

        title = broadcast?.title

        let urlImageString = broadcast?.image
        let urlImage = URL(string: urlImageString!)

        titleLabel.text = broadcast?.title
        imageView.load(url: urlImage!)
    }
}

1 Ответ

1 голос
/ 29 мая 2020

Освободить / освободить и остановить AVPlayer и AVPlayerItem перед возвратом к контроллеру табличного представления

avPlayer.pause()
avPlayer.cancelPendingPrerolls() // stops network requests
avPlayer.replaceCurrentItem(with: nil)
...