问题
I am new to Swift and making an audio app using AVAudioPlayer. I am using a remote URL mp3 file for the audio, and this works when it's static.
For my use case, I want to pull a URL for an mp3 file from a JSON array and then pass it into the AVAudioPlayer to run.
If I move the
AVAudioPlayerblock into theViewDidLoadand make the mp3 file a static URL, it will run fine.Then, when I move this code into my block that extracts an mp3 url from JSON, I can
printthe URL successfully. But when I pass it into my audio player, problems arise. Here's the code.override func viewDidLoad() { super.viewDidLoad() let url = URL(string: "http://www.example.com/example.json") URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in guard let data = data, error == nil else { return } let json: Any? do{ json = try JSONSerialization.jsonObject(with: data, options: []) } catch{ return } guard let data_list = json as? [[String:Any]] else { return } if let foo = data_list.first(where: {$0["episode"] as? String == "Example Preview"}) { self.audiotest = (foo["audio"] as? String)! print(self.audiotest) // this prints // where i'm passing it into the audio player if let audioUrl = URL(string: self.audiotest) { // then lets create your document folder url let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // lets create your destination file url let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent) //let url = Bundle.main.url(forResource: destinationUrl, withExtension: "mp3")! do { audioPlayer = try AVAudioPlayer(contentsOf: destinationUrl) } catch let error { print(error.localizedDescription) } } // end player // ....
Specifically, I get an error Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value when clicking a play button IBAction that is connected to the audio player. Finally, that action function looks like this:
@IBAction func playPod(_ sender: Any) {
audioPlayer.play()
}
Do you know where I'm going wrong? I'm confused as to why I can't print the URL and also get a response that the URL is nil in the same block, but maybe that's an asynchronous thing.
回答1:
The problem is that you didn't save the mp3 file to documents and trying to play it
this line
audioPlayer = try AVAudioPlayer(contentsOf: destinationUrl)
assumes that there is a saved mp3 file in that path , but acutally there is no files you appended the audio extension on the fly
besides for steaming audio from a remote server, use AVPlayer instead of AVAudioPLayer. AVPlayer Documentation
Also try this with urls parsed from json
var urlStr = (foo["audio"] as? String)!
self.audiotest = urlStr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
来源:https://stackoverflow.com/questions/48431455/using-avaudioplayer-with-dynamic-url-in-swift-3-causing-thread-errors