Swift - 使用AVPlayer制作一个音乐播放器1(带播放时间和播放进度)
作者:hangge | 2017-06-07 08:10
(本文代码已升级至Swift4)
过去我们可以使用 Media Player 框架 MPMoviePlayerController 来播放视频、音频。但自 iOS9.0 起,这个便被废除。取而代之的便是 AVFoundation 框架的 AVPlayer。
1,AVPlayer介绍
(1)AVPlayer 可以用来播放视频,也可以播放任何 iOS 支持的音频。
(2)AVPlayer 既可以播放本地音频,可以播放网络音频(在线音频)。
(3)要注意的是,如果播放远程音频,AVPlayer 同样是全部加载到本地后才开始播放,而不是以流媒体的形式播放。
2,效果图
(1)下面使用 AVPlayer 制作一个音乐播放器。
(2)点击按钮可以时音乐在“播放”和“暂停”两个状态间切换。
(3)播放过程中进度条和旁边的标签会实时显示当前的进度。
(4)进度条滑块可以自由拖动,并播放对应时间点的音乐。
3,样例代码
import UIKit import AVFoundation class ViewController: UIViewController { //播放按钮 @IBOutlet weak var playButton: UIButton! //可拖动的进度条 @IBOutlet weak var playbackSlider: UISlider! //当前播放时间标签 @IBOutlet weak var playTime: UILabel! //播放器相关 var playerItem:AVPlayerItem? var player:AVPlayer? override func viewDidLoad() { super.viewDidLoad() //初始化播放器 let url = URL(string: "http://www.hangge.com/music.mp3") playerItem = AVPlayerItem(url: url!) player = AVPlayer(playerItem: playerItem!) //设置进度条相关属性 let duration : CMTime = playerItem!.asset.duration let seconds : Float64 = CMTimeGetSeconds(duration) playbackSlider!.minimumValue = 0 playbackSlider!.maximumValue = Float(seconds) playbackSlider!.isContinuous = false //播放过程中动态改变进度条值和时间标签 player!.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: DispatchQueue.main) { (CMTime) -> Void in if self.player!.currentItem?.status == .readyToPlay { //更新进度条进度值 let currentTime = CMTimeGetSeconds(self.player!.currentTime()) self.playbackSlider!.value = Float(currentTime) //一个小算法,来实现00:00这种格式的播放时间 let all:Int=Int(currentTime) let m:Int=all % 60 let f:Int=Int(all/60) var time:String="" if f<10{ time="0\(f):" }else { time="\(f)" } if m<10{ time+="0\(m)" }else { time+="\(m)" } //更新播放时间 self.playTime!.text=time } } } //播放按钮点击 @IBAction func playButtonTapped(_ sender: Any) { //根据rate属性判断当天是否在播放 if player?.rate == 0 { player!.play() playButton.setTitle("暂停", for: .normal) } else { player!.pause() playButton.setTitle("播放", for: .normal) } } //拖动进度条改变值时触发 @IBAction func playbackSliderValueChanged(_ sender: Any) { let seconds : Int64 = Int64(playbackSlider.value) let targetTime:CMTime = CMTimeMake(seconds, 1) //播放器定位到对应的位置 player!.seek(to: targetTime) //如果当前时暂停状态,则自动播放 if player!.rate == 0 { player?.play() playButton.setTitle("暂停", for: .normal) } } //页面显示时添加歌曲播放结束通知监听 override func viewWillAppear(_ animated: Bool) { NotificationCenter.default.addObserver(self, selector: #selector(finishedPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem) } //页面消失时取消歌曲播放结束通知监听 override func viewWillDisappear(_ animated: Bool) { NotificationCenter.default.removeObserver(self) } //歌曲播放完毕 @objc func finishedPlaying(myNotification:NSNotification) { print("播放完毕!") let stopedPlayerItem = myNotification.object as! AVPlayerItem stopedPlayerItem.seek(to: kCMTimeZero, completionHandler: nil) playButton.setTitle("播放", for: .normal) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }源码下载:hangge_1668.zip
全部评论(2)
//页面消失时取消歌曲播放结束通知监听
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self)
}
这句话没有效果, 我点击tabbar切换页面后. 声音还是没有停止.
站长回复:这个只是取消监听,如果想要停止声音的话,可以在这个方法里再加个 player.pause()
104行的.seek(to:) 这个好像在IOS11 不能用了
站长回复:多谢你的提醒,这里语法确实有变,文章代码现已更新。