在 Swift 3 中使用带有动态 URL 的 AVAudioPlayer 导致线程错误

Posted

技术标签:

【中文标题】在 Swift 3 中使用带有动态 URL 的 AVAudioPlayer 导致线程错误【英文标题】:Using AVAudioPlayer with Dynamic URL in Swift 3 causing Thread Errors 【发布时间】:2018-01-24 20:56:42 【问题描述】:

我是 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: $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
    
    // ....
    

具体来说,我在单击连接到音频播放器的播放按钮 IBAction 时收到错误 Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value。最后,动作函数如下所示:

  @IBAction func playPod(_ sender: Any) 
    audioPlayer.play() 

你知道我哪里出错了吗?我很困惑为什么我不能打印 URL 并且还得到一个响应,即 URL 在同一个块中为零,但也许这是一个异步的事情。

【问题讨论】:

【参考方案1】:

问题是您没有将 mp3 文件保存到文档并尝试播放它

这一行

    audioPlayer = try AVAudioPlayer(contentsOf: destinationUrl)

假设该路径中有一个保存的 mp3 文件,但实际上没有您在运行中附加音频扩展名的文件

除了从远程服务器传输音频,使用 AVPlayer 代替 AVAudioPLayer。 AVPlayer Documentation

也可以尝试使用从 json 解析的 url

  var urlStr = (foo["audio"] as? String)!

  self.audiotest = urlStr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

【讨论】:

有趣。我确实将它保存在以前的视图中,但也许我在访问时遇到了问题。您是否知道它为什么会在块外播放(当我使 URL 相同但将其硬编码为值而不是响应 var 时)?这就是我不明白的。 https路径有空格吗 嘿,我验证了你的答案。我在前一个视图控制器中添加了一个下载按钮。很酷的是,通过在第二个 VC 中定位该 URL(如上所示),它现在知道在我认为很难的包中找到它。非常感谢!

以上是关于在 Swift 3 中使用带有动态 URL 的 AVAudioPlayer 导致线程错误的主要内容,如果未能解决你的问题,请参考以下文章

Swift:使用 UIImageView 显示带有从数组 [0..4] 中获取的 URL 的图像

带有 Swift 3 的 Alamofire 4.3,POST 请求不适用于 URL 参数

在滚动视图中动态隐藏状态栏时滞后/屏幕冻结(Swift 3)

Swift 3 - 带有 Tap Gesture 的图像视图

从带有 URL 的 mp3 文件中获取元数据(swift)

IOS - 如何在 Swift 3 中从 JSON 中捕获动态数组维度