I am trying to play a sound from a background thread using an instance of an AVAudioPlayer in Swift 5. Most of the time, it will be successful. But once in a while the audio player fails to play a sound.
It appears as though calling play() twice, or prepareToPlay() and then play() in a row somehow fixes the problem, but this doesn't seem like a good solution to me, as I am worried that this still doesn't guarantee that it will play successfully.
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
    }
}
I call the methods in this order:
setUpAudio()
startNewAudio()
setPlay()
I can't figure out the problem—I really want to just call play() once and have everything work fine.
 
    