从后台线程播放AVAudioPlayer的实例有时会失败

时间:2019-05-31 23:39:48

标签: ios swift avaudioplayer dispatch-queue ios-multithreading

我正在尝试使用Swift 5中的AVAudioPlayer实例从后台线程播放声音。大多数情况下,它将是成功的。但是有时音频播放器无法播放声音。

似乎两次调用play()或连续调用prepareToPlay()然后再play()以某种方式解决了问题,但这对我来说似乎不是一个好的解决方案,因为我担心这仍然不保证它将成功播放。

contentX = ['a12334111','b3215555','c444389663']
content = [  12334111,  3215555 , 44489663]      # this OK

a =  content[1]
b = a.to_s[0..3]  # this string need to add
puts 'a:       ' + a.to_s + '  b:  ' + b.to_s

s = content.inject(:+)
s2 = contentX[0..3].inject(:+) #  Error here, no values calculated

puts 'Sum    ' + s.to_s
puts 'Sum2   ' + s2.to_s

Sum2  = 888

我按以下顺序调用方法:

func setUpAudio() {
    AVAudioSession.sharedInstance().perform(NSSelectorFromString("setCategory:error:"), with: AVAudioSession.Category.playback)
    try! AVAudioSession.sharedInstance().setActive(true)
    NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption), name: AVAudioSession.interruptionNotification, object: nil)
}

func startNewAudio() {
    let destinationData = Destinations.getDestinations()
    var audio = destinationData[currentStop]!["audio"] as! String
    if inTransit {
        audio = destinationData[Paths.tourOrder[currentIndex + 1]]!["transit_audio"] as! String
    }
    let sound = NSURL(fileURLWithPath: Bundle.main.path(forResource: audio, ofType: "mp3", inDirectory: "audio")!)
    try! audioPlayer = AVAudioPlayer(contentsOf: sound as URL)
    audioPlayer.delegate = self
    currentTime = 0
    setPlay()
}

func setPlay() {
    paused = false
    pauseButton.setImage(UIImage(named: "pause"), for: .normal)
    pauseButton.isEnabled = true
    audioPlayer.currentTime = currentTime
    DispatchQueue.global(qos: .background).async {
        self.audioPlayer.play()
        print(self.audioPlayer.isPlaying) // returns false sometimes
    }
}

我想不通这个问题,我真的想只打一次play()并使一切正常。

1 个答案:

答案 0 :(得分:0)

没有理由在后台线程上说play;播放声音不会阻塞主线程。此外,没有理由认为AVAudioPlayer是线程安全的。而且您的代码肯定不是线程安全的,因为您正在从不同线程同时与音频播放器通话。因此,您使用的线程不正确。讨论错误的行为结果毫无意义。删除后台线程,然后尝试以正确的方式执行代码。如果仍然有问题,我们可以谈谈。