快速按下声音按钮时出错

问题描述 投票:0回答:1

我有一个音量切换按钮。当我按下按钮时,会调用暂停或播放,但会出现一些淡入淡出。问题是,如果我快速按两次按钮,例如暂停然后播放,我会听到音量跳跃。此外,如果我快速调用播放,然后猛按并调用暂停,那么在播放模式下,由于延迟调用

DispatchQueue
,音频将停止。如何解决这个问题?

视图控制器:

class ViewController: UIViewController {

    @objc func soundState() {
        if defaults.string(forKey: "sound") == "false" {
            audio.pause(volume: 0.0, duration: 3.0)
            
        } else if defaults.string(forKey: "sound") == "true" {
            audio.play(volume: 1.0, duration: 3.0) 
        }
    }

}

音频控制器:

class Audio: NSObject, AVAudioPlayerDelegate {

    var audioPlayer: AVAudioPlayer!
    
    func loopedAudio(fileName: String, fileExtension: String) {
                
        try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        try? AVAudioSession.sharedInstance().setActive(true)
        
        let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension)
        
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url!)
            audioPlayer.prepareToPlay()
            audioPlayer.delegate = self
            audioPlayer.numberOfLoops = -1
        } catch {
            print("error")
        }
        
    }

    func play(volume: Float, duration: Double) {
        audioPlayer.volume = 0
        audioPlayer.play()
        audioPlayer.setVolume(volume, fadeDuration: duration)
    }
    
    func pause(volume: Float, duration: Double) {
        audioPlayer.volume = 1
        audioPlayer.setVolume(volume, fadeDuration: duration)
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            self.audioPlayer.pause()
        }
    }

}
ios swift uibutton avaudioplayer dispatch-async
1个回答
0
投票

出现您的问题是因为您的一项操作

pause
被延迟,而您的另一项操作
play
是即时的。 这意味着如果您快速改变状态,可能不再需要他们延迟行动。

解决方案是显式跟踪所需的状态,以避免不必要的延迟操作:

enum PlaybackState {
    case playing
    case paused
}

class Audio: NSObject, AVAudioPlayerDelegate {

    var playbackState: PlaybackState = .paused

    var audioPlayer: AVAudioPlayer!
    
    func loopedAudio(fileName: String, fileExtension: String) {
                
        try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        try? AVAudioSession.sharedInstance().setActive(true)
        
        let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension)
        
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: url!)
            audioPlayer.prepareToPlay()
            audioPlayer.delegate = self
            audioPlayer.numberOfLoops = -1
        } catch {
            print("error")
        }
        
    }

    func play(volume: Float, duration: Double) {
        audioPlayer.volume = 0
        audioPlayer.play()
        audioPlayer.setVolume(volume, fadeDuration: duration)
        self.playbackState = .playing
    }
    
    func pause(volume: Float, duration: Double) {
        audioPlayer.volume = 1
        audioPlayer.setVolume(volume, fadeDuration: duration)
        self.playbackState = paused
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            guard self.playbackState == .paused else {
                return
            }
            self.audioPlayer.pause()    
        }
    }

}

现在,当你的

dispatchAfter
执行时,它会首先检查是否仍然需要
pause
状态。 如果没有,它将简单地返回,并继续播放音频。

© www.soinside.com 2019 - 2024. All rights reserved.