我有一个用于音频播放的静态AVPlayer,我需要确保在控制器被销毁并重放音频后,音频会继续播放。我已经尝试了几个月来解决这个问题,但都没有取得任何成功,3个月前我被问到关于这个话题的问题到目前为止还没有答案,请帮助一劳永逸地解决这个问题
这是我的代码:
class ViewControllerAudioDetail: UIViewController {
static var avPlayer = AVPlayer()
static var status = false
var timeSlider = false
fileprivate let seekDuration: Float64 = 10
fileprivate let seekDurationThirty: Float64 = 30
var sliderEndTime:Any!
var sliderDurationTime:Any!
var mod = [Modal]()
@IBOutlet weak var ImageView: UIImageView!
@IBOutlet weak var startTime: UILabel!
@IBOutlet weak var endTime: UILabel!
@IBOutlet weak var sliderSong: UISlider!
@IBOutlet weak var name: UILabel!
@IBOutlet weak var Volume: UISlider!
@IBOutlet weak var iconChange: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
name.text = mod[thisSong].AudioName
ImageView.image = mod[0].ImageViewAudio
player(urlSong:mod[thisSong].UrlName!)
self.timeSlider = true
ViewControllerAudioDetail.status = true
Status()
}
@IBAction func sliderSong(_ sender: UISlider) {
//перемотка аудиозвука
let duration = CMTimeGetSeconds(ViewControllerAudioDetail.avPlayer!.currentItem!.asset.duration)
let value = sliderSong.value
let durationToSeek = Float(duration) * value
ViewControllerAudioDetail.avPlayer?.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),ViewControllerAudioDetail.avPlayer!.currentItem!.duration.timescale)) { [](state) in
if (self.iconChange.currentImage?.isEqual(UIImage(named: "Play.png")))! {
ViewControllerAudioDetail.avPlayer?.pause()
} else if (self.iconChange.currentImage?.isEqual(UIImage(named: "Pause.png")))!{
ViewControllerAudioDetail.avPlayer?.play()
}
}
}
func Status(){
timeSlider = false
if ViewControllerAudioDetail.status == true {
iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)
ViewControllerAudioDetail.avPlayer.play()
} else {
iconChange.setImage(UIImage(named:"Play.png"), for: .normal)
ViewControllerAudioDetail.avPlayer.pause()
}
}
@IBAction func Play(_ sender: Any) {
if ViewControllerAudioDetail.avPlayer.rate == 0 && ViewControllerAudioDetail.status == false{
ViewControllerAudioDetail.status = true
ViewControllerAudioDetail.avPlayer.play()
ViewControllerAudioDetail.avPlayer.rate = 1.0
iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)
if timeSlider == false {
sliderDurationTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: {
(CMTime) -> Void in
self.updateProgressBar()
})
}
} else {
ViewControllerAudioDetail.status = false
ViewControllerAudioDetail.avPlayer.rate = 0.0
ViewControllerAudioDetail.avPlayer.pause()
iconChange.setImage(UIImage(named:"Play.png"), for: .normal)
}
}
func player(urlSong:String) {
let url = URL(string: urlSong)
let playerItem = AVPlayerItem(url: url!)
ViewControllerAudioDetail.avPlayer = AVPlayer(playerItem:playerItem)
NotificationCenter.default.addObserver(self, selector:#selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)
sliderDurationTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: {
(CMTime) -> Void in
self.updateProgressBar()
})
sliderEndTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in
let duration = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer.currentItem!.asset.duration))
self?.sliderSong.value = Float(CMTimeGetSeconds(time)) / Float(duration)
}
let duration = CMTimeGetSeconds(ViewControllerAudioDetail.avPlayer.currentItem!.asset.duration)
let minutesTextOut = Int(duration) / 60 % 60
let secondsTextOut = Int(duration) % 60
let strDuration = String(format:"%02d:%02d", minutesTextOut, secondsTextOut)
endTime.text = strDuration
}
func updateProgressBar(){
let timeNow = Int(ViewControllerAudioDetail.avPlayer.currentTime().value) / Int(ViewControllerAudioDetail.avPlayer.currentTime().timescale)
let minutesText = timeNow / 60
let secondsText = timeNow % 60
let duration = String(format:"%02d:%02d", minutesText, secondsText)
startTime.text = duration
}
答案 0 :(得分:2)
我想,你可能有一个静态变量playerDidInit
用作守卫,然后在你第一次初始化true
时切换AVPlayer
这样的变量。为了能够再次初始化,如果您想要更改currentSong
,那么您可以执行以下操作:
static var playerDidInit = false
static var currentSong:String?
//....//
func player(urlSong:String) {
if !playerDidInit || urlSong != currentSong {
playerDidInit = true
currentSong = urlSong
let url = URL(string: urlSong)
let playerItem = AVPlayerItem(url: url!)
ViewControllerAudioDetail.avPlayer = AVPlayer(playerItem:playerItem)
}