Reputation: 595
I use Alamofire to download the iTunes search Api's trial music.
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)
}
}
}
}
}
Upvotes: 0
Views: 3496
Reputation: 6982
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. 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.
Also, you use force unwrapping operator - !
- a lot, which is:
1) incorrect
2) unsafe
Use either if let
construct or guard
statement
What you need to to is store the player as instance variable of your FirstViewController
class.
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)
}
}
}
}
}
Upvotes: 2
Reputation: 4946
Just move audioPlayer to controller
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......
}
Upvotes: 0