首页 > 解决方案 > 使用 AVAudioPlayer 无法通过 Swift 4 播放 .m4a

问题描述

我使用 Alamofire 下载 iTunes 搜索 Api 的试用音乐。
当我下载完成后,我想播放音乐。
我尝试修复它,但它也没有声音可以播放。
如何解决这个问题呢?
谢谢。

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)
                }

            }
        }

    }
}

标签: iosswiftavaudioplayer

解决方案


这个问题是由audioPlayer一个局部变量引起的,因此当你离开完成闭包的范围时它会被释放。因为audioPlayer没有保留在其他任何地方,所以当您离开闭包的范围时,audioPlayer引用计数等于0,这会导致 ARC 释放它。

此外,您使用强制展开运算符 - !- 很多,即:
1)不正确
2)不安全
使用if let构造或guard语句

您需要将播放器存储为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)
                }
            }
        }
    }
}

推荐阅读