【问题标题】:Turn off audio playing?关闭音频播放?
【发布时间】:2019-03-07 18:00:30
【问题描述】:

我正在使用AVPlayer 播放来自URL 的音频。一切正常,但是当我在不同的ViewController 中时,我不知道如何停止当前的音频播放我不想在viewWillDisappear() 中调用player.pause(),因为我想在特定情况下停止它,但是当应用处于非活动状态时,我仍希望在后台播放音频。

当应用处于非活动状态时,我在 Xcode 应用设置中开启了后台播放

第二个问题:我可以改进这门课还是一切都好?

protocol AVPlayerServiceDelegate {
    func playerDidUpdateCurrentPlayingTime(_ time: CMTime)

}

class AVPlayerService {
    static let instance = AVPlayerService()

    private var audioPlayer: AVPlayer!
    public weak var delegate: AVPlayerServiceDelegate?

    func setupPlayer(forURL url: URL) {
        let playerItem: AVPlayerItem = AVPlayerItem(url: url)
        audioPlayer = AVPlayer(playerItem: playerItem)
        audioPlayer.play()

        audioPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1), queue: DispatchQueue.main) { (CMTime) -> Void in
            if self.audioPlayer.currentItem?.status == .readyToPlay {
                self.delegate?.playerDidUpdateCurrentPlayingTime(self.audioPlayer.currentTime())
            }
        }
    }

    var isPlaying: Bool {
        return audioPlayer.isPlaying
    }

    var isPaused: Bool {
        return audioPlayer.isPaused
    }

    var rate: Float {
        return audioPlayer.rate
    }

    func seek(to time: CMTime) {
        audioPlayer.seek(to: time)
    }

    func seekToBeginning() {
        audioPlayer.seek(to: CMTimeMake(value: 0, timescale: 1))
    }

    func replay() {
        audioPlayer.seek(to: CMTimeMake(value: 0, timescale: 1))
        audioPlayer.play()
    }

    func pause() {
        if let audioPlayer = audioPlayer {
            audioPlayer.pause()
        }
    }

    func play() {
        audioPlayer.play()
    }

    func freshInstance() {
        audioPlayer = AVPlayer()
    }

    var assetDuration: CMTime {
        get {
            return audioPlayer.currentItem!.asset.duration
        }
    }
    }

【问题讨论】:

    标签: ios iphone xcode avfoundation swift4.2


    【解决方案1】:

    您需要一种机制来与player 对象通信,以便对其执行操作。
    有很多方法可以解决。

    就我个人而言,我会为播放器创建一个专门的类来处理实例化、加载音频资源、播放、暂停等。
    然后我要么让这个类成为一个单例,这样我就可以从任何地方访问它,或者将它注入并将它传递给其他将使用它的类。

    基本示例:

    class MyAudioPlayer {
        static let shared = MyAudioPlayer()
        
        private var player: AVAudioPlayer?
        
        func load(_ url: URL) {
            player = try? AVAudioPlayer(contentsOf: url)
        }
    
        func play(url: URL) {
            load(url: url)
            player?.play()
        }
    
        func pause() {
            player?.pause()
        }
    
        func stop() {
            player?.stop()
        }     
    }
    

    从应用内的任何地方发送操作:

    MyAudioPlayer.shared.play(someURL)
    MyAudioPlayer.shared.pause()
    

    至于即使应用程序未处于活动状态也需要在后台播放(可能在AppDelegate

    try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, 
                                                     with: .duckOthers)
    try? AVAudioSession.sharedInstance().setActive(true)
    UIApplication.shared.beginReceivingRemoteControlEvents()
    

    【讨论】:

    • 谢谢,为什么我不能公开 avplayer 来改变属性而不是做一个函数?
    • @SwiftNewling 如果你愿意,你可以,没问题。我使用函数来更好地控制动作。
    • 直接从 viewController 访问播放器并不像我现在测试的那样好。它没有得到正确的有效信息,比如它是否在播放。它告诉我这是假的,但它确实在播放。如果我在我的服务中编写该函数,它可以正常工作
    • @SwiftNewling 我将我的 cmets 更改为与我的答案相符,因为我认为我可能误解了你
    • @SwiftNewling 我建议自动删除多播委托,因为您需要一组委托。你现在拥有的东西不需要自动删除,从某种意义上说,已经是因为weak。一切都很好,编码愉快:)
    猜你喜欢
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2017-10-16
    • 2021-10-02
    相关资源
    最近更新 更多