Adeel Noor Adeel Noor - 17 days ago 12
Swift Question

Play audio file using AVAudioPlayer swift

I am downloading the audio message first then play it using Avaudioplayer

downloadTask = NSURLSession.sharedSession().downloadTaskWithURL(urlStr, completionHandler: { (URL, response, error) -> Void in

self.play(URL!)


})
downloadTask


This works fine, but if I call play(URL) method after saving the response URL that I have stored in NSUserDefaults. The URL is same in both cases. I have checked it. its something like:


file:///Users/mymac/Library/Developer/CoreSimulator/Devices/X-CD91-XXXXXXX-XXX-XXXXXX/data/Containers/Data/Application/XXXXXXX-XXXX-XXXXXXXXXX/tmp/CFNetworkDownload_InUTA3.tmp


Passing this file url to:

func play(url : NSURL) {

do {
player = try AVAudioPlayer(contentsOfURL: url)
player.prepareToPlay()
player.play()

} catch let error as NSError {
//self.player = nil
print(error.localizedDescription)

} catch {

print("AVAudioPlayer init failed")
}

}


Url path is same, but the audioPlayer is unable to play the sound, it shows the following error:


The operation couldn’t be completed. (OSStatus error 2003334207.)


Can anyone guide me in this regard?

Thanks.

Answer

As can be seen from the comments above the problem was that the downloaded file was not moved before completing the completionHandler of the downloadTask method.

As it says in the description of the location parameter

The location of a temporary file where the server’s response is stored. You must move this file or open it for reading before your completion handler returns. Otherwise, the file is deleted, and the data is lost.

Therefore, in your completionHandler you must move the file to another location that you control before ending the completionHandler.

This probably also explains the crash. If the "temp" URL is saved to UserDefaults in the completionHandler then that URL is no longer valid when the completionHandler has completed. So when you then later call

play(URL!)

with a force unwrapped URL that is now invalid, you get a crash.

Therefore, as an extra safety measure, try unwrapping the URL before trying to use it:

if let url = urlFromUserDefaults {
    play(url)
}

Hope that helps you.

Comments