在 Swift 3 中使用带有 Dynamic URL 的 AVAudioPlayer 导致线程错误
Using AVAudioPlayer with Dynamic URL in Swift 3 causing Thread Errors
我是 Swift 的新手,正在使用 AVAudioPlayer
制作音频应用程序。我正在为音频使用远程 URL mp3 文件,这在它是静态的时候有效。
对于我的用例,我想从 JSON 数组中提取 mp3 文件的 URL,然后将其传递到 AVAudioPlayer
到 运行。
如果我将 AVAudioPlayer
块移动到 ViewDidLoad
并将 mp3 文件设为静态 URL,它将 运行 正常。
然后,当我将此代码移动到从 JSON 中提取 mp3 url 的块中时,我可以 print
成功 URL .但是当我将它传递到我的音频播放器时,问题就出现了。这是代码。
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: {[=12=]["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
// ....
具体来说,我在单击连接到音频播放器的播放按钮 IBAction
时收到错误消息 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
。最后,该动作函数如下所示:
@IBAction func playPod(_ sender: Any) {
audioPlayer.play()
}
你知道我错在哪里吗?我很困惑为什么我不能打印 URL 并且在同一个块中得到 URL 为 nil 的响应,但也许这是一个异步的事情。
问题是您没有将 mp3 文件保存到文档并尝试播放
这一行
audioPlayer = try AVAudioPlayer(contentsOf: destinationUrl)
假定该路径中有一个已保存的 mp3 文件,但实际上没有您即时附加音频扩展名的文件
除了从远程服务器传输音频外,请使用 AVPlayer 而不是 AVAudioPLayer。
AVPlayer Documentation
也可以尝试使用从 json
解析的网址
var urlStr = (foo["audio"] as? String)!
self.audiotest = urlStr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
我是 Swift 的新手,正在使用 AVAudioPlayer
制作音频应用程序。我正在为音频使用远程 URL mp3 文件,这在它是静态的时候有效。
对于我的用例,我想从 JSON 数组中提取 mp3 文件的 URL,然后将其传递到 AVAudioPlayer
到 运行。
如果我将
AVAudioPlayer
块移动到ViewDidLoad
并将 mp3 文件设为静态 URL,它将 运行 正常。然后,当我将此代码移动到从 JSON 中提取 mp3 url 的块中时,我可以
print
成功 URL .但是当我将它传递到我的音频播放器时,问题就出现了。这是代码。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: {[=12=]["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 // ....
具体来说,我在单击连接到音频播放器的播放按钮 IBAction
时收到错误消息 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
。最后,该动作函数如下所示:
@IBAction func playPod(_ sender: Any) {
audioPlayer.play()
}
你知道我错在哪里吗?我很困惑为什么我不能打印 URL 并且在同一个块中得到 URL 为 nil 的响应,但也许这是一个异步的事情。
问题是您没有将 mp3 文件保存到文档并尝试播放
这一行
audioPlayer = try AVAudioPlayer(contentsOf: destinationUrl)
假定该路径中有一个已保存的 mp3 文件,但实际上没有您即时附加音频扩展名的文件
除了从远程服务器传输音频外,请使用 AVPlayer 而不是 AVAudioPLayer。 AVPlayer Documentation
也可以尝试使用从 json
解析的网址 var urlStr = (foo["audio"] as? String)!
self.audiotest = urlStr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)