简体   繁体   English

使用AVAudioPlayer无法通过Swift 4播放.m4a

[英]Using AVAudioPlayer fail to play .m4a by Swift 4

I use Alamofire to download the iTunes search Api's trial music. 我使用Alamofire下载iTunes搜索Api的试用音乐。
And when I download finished, I want to play the music. 当我完成下载后,我想播放音乐。
I try to fix it, but it also no sounds to play. 我尝试修复它,但也没有声音播放。
How to solve this problem? 如何解决这个问题呢?
Thanks. 谢谢。

import UIKit
import AVFoundation
import Alamofire
import CryptoSwift

class FirstViewController: UIViewController {

    let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"

    override func viewDidLoad() {
        super.viewDidLoad()

        let destination: DownloadRequest.DownloadFileDestination = { _, _ in
            let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            let fileName = self.urlString.md5()
            let fileURL = documentsURL.appendingPathComponent("\(fileName).m4a")
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }

        Alamofire.download(urlString, to: destination).response { response in

            if response.error == nil {

                var audioPlayer: AVAudioPlayer!

                do {
                    audioPlayer = try AVAudioPlayer(contentsOf: response.destinationURL!)
                    audioPlayer.prepareToPlay()
                    audioPlayer.play()
                } catch {
                    print("Error:", error.localizedDescription)
                }

            }
        }

    }
}

The problem is caused by the fact that audioPlayer is a local variable, therefore it gets deallocated when you leave the scope of completion closure. 问题是由于audioPlayer是局部变量,因此,当您离开完成关闭范围时,它会被释放。 Because audioPlayer isn't retained anywhere else, the moment you leave the closure's scope, audioPlayer reference count is equal to 0 , which causes ARC to deallocate it. 因为audioPlayer不会保留在其他任何地方,所以当您离开闭包的作用域时, audioPlayer引用计数就等于0 ,这将导致ARC取消分配它。

Also, you use force unwrapping operator - ! 另外,您可以使用强制展开运算符- ! - a lot, which is: -很多,这是:
1) incorrect 1)不正确
2) unsafe 2)不安全
Use either if let construct or guard statement if let构造或guard语句使用

What you need to to is store the player as instance variable of your FirstViewController class. 您需要将播放器存储为FirstViewController类的实例变量。

class FirstViewController: UIViewController {

    let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"

    var audioPlayer : AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        // (...)

        Alamofire.download(urlString, to: destination).response { [weak self] (response) in

            if response.error == nil {

                guard let url = response.destinationURL else { return }

                do {
                    self?.audioPlayer = try AVAudioPlayer(contentsOf:  url)
                    self?.audioPlayer?.prepareToPlay()
                    self?.audioPlayer?.play()
                } catch {
                    print("Error:", error.localizedDescription)
                }
            }
        }
    }
}

Just move audioPlayer to controller 只需将audioPlayer移至控制器

class FirstViewController: UIViewController {

    let urlString = "https://audio-ssl.itunes.apple.com/apple-assets-us-std-000001/AudioPreview18/v4/9c/db/54/9cdb54b3-5c52-3063-b1ad-abe42955edb5/mzaf_520282131402737225.plus.aac.p.m4a"
    var audioPlayer: AVAudioPlayer?

   //Downloading code......
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM