最近准备将项目转化为OC与swift混合开发,试着写一个swift音乐播放器的demo,体会到了swift相对OC的优势所在,废话不多说,先上效果图: ps:身为杰伦的铁粉,demo的主题必须跟杰伦有关,哈哈!而且自我感觉我有转型UI的天赋,有木有?
一、导入OC文件 创建好swift项目之后,导入OC工具类文件,Xcode会自动生成桥接文件
打开这个文件,在开头导入OC工具类的头文件,就可以调用OC工具类了
// // Use this file to import your target's public headers that you would like to expose to Swift. // #import "UIView+Frame.h"二、界面绘制 这里方便起见,没有考虑性能问题,只是简单的demo,所以直接创建十个音乐按钮,加上一个播放按钮和一个暂停按钮。十个乐曲按钮放在一个UIScrollView上面。而且播放的音乐是本地音乐,首先在viewDidLoad前创建全局变量,代码如下:
var btnIndex = 0 let arrMusicName = ["蒲公英的约定","窃爱","退后","告白气球","阳光宅男","甜甜的","彩虹","心雨","哪里都是你","说好的幸福呢"] let btnPlay:UIButton = UIButton(type:.System) let btnPause:UIButton = UIButton(type:.System) override func viewDidLoad() {界面绘制代码如下:
let SCREEN_W = UIScreen.mainScreen().bounds.size.width let SCREEN_H = UIScreen.mainScreen().bounds.size.height let ivBack:UIImageView = UIImageView(frame:CGRect(x:0, y:20, width:SCREEN_W, height:SCREEN_H)) ivBack.image = UIImage(named:"aa.jpg") self.view.addSubview(ivBack) let lbTitle:UILabel = UILabel(frame:CGRect(x:0, y:20, width:SCREEN_W, height:44)) lbTitle.text = "LXY的杰伦情歌" lbTitle.textColor = UIColor.whiteColor() lbTitle.textAlignment = NSTextAlignment.Center lbTitle.backgroundColor = UIColor.blackColor() lbTitle.alpha = 0.2 self.view.addSubview(lbTitle) let scv:UIScrollView = UIScrollView(frame:CGRect(x:0, y:64, width:SCREEN_W, height:SCREEN_H - 74 - 44)) scv.backgroundColor = UIColor.clearColor() self.view.addSubview(scv) var boom:Int = 0 for st in arrMusicName { print(st) if let index = arrMusicName.indexOf(st) { let btn:UIButton = UIButton(type:.System) btn.backgroundColor = UIColor.whiteColor() btn.alpha = 0.5 btn.setTitle(st, forState: UIControlState.Normal) btn.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal) btn.titleLabel?.font = UIFont.systemFontOfSize(16) btn.layer.masksToBounds = true btn.layer.shadowOffset = CGSizeMake(0, 10) btn.layer.shadowColor = UIColor.grayColor().CGColor btn.layer.shadowOpacity = 1 btn.layer.shadowRadius = 10 btn.layer.cornerRadius = 6 btn.tag = index //传递触摸对象(即点击的按钮),需要在定义action参数时,方法名称后面带上冒号 btn.addTarget(self, action:#selector(play(_:)), forControlEvents:.TouchUpInside) if index%2 == 0 { btn.frame = CGRectMake(SCREEN_W/9, 20 + (SCREEN_W/3 + SCREEN_W/9)*CGFloat(index/2),SCREEN_W/3,SCREEN_W/3) }else { btn.frame = CGRectMake(5*SCREEN_W/9, 20 + (SCREEN_W/3 + SCREEN_W/9)*CGFloat(index/2),SCREEN_W/3,SCREEN_W/3) } scv.addSubview(btn) boom = Int(btn.bottom) } } scv.contentSize = CGSizeMake(SCREEN_W,CGFloat(boom + 20)) btnPlay.frame = CGRectMake(0, scv.bottom, SCREEN_W/2 - 10, 44) btnPlay.backgroundColor = UIColor.whiteColor() btnPlay.alpha = 0.5 btnPlay.setTitle("播放", forState: UIControlState.Normal) btnPlay.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal) btnPlay.titleLabel?.font = UIFont.systemFontOfSize(16) btnPlay.addTarget(self, action:#selector(MPMediaPlayback.play), forControlEvents:.TouchUpInside) btnPlay.hidden = true self.view.addSubview(btnPlay) btnPause.frame = CGRectMake(10 + SCREEN_W/2, scv.bottom, SCREEN_W/2 - 10, 44) btnPause.backgroundColor = UIColor.whiteColor() btnPause.alpha = 0.5 btnPause.setTitle("暂停", forState: UIControlState.Normal) btnPause.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal) btnPause.titleLabel?.font = UIFont.systemFontOfSize(16) btnPause.addTarget(self, action:#selector(MPMediaPlayback.pause), forControlEvents:.TouchUpInside) btnPause.hidden = true self.view.addSubview(btnPause) } func play(btn: UIButton){ btnIndex = btn.tag let music = arrMusicName[btn.tag] let path = NSBundle.mainBundle().pathForResource(music, ofType: "mp3") let pathURL=NSURL(fileURLWithPath: path!) do { audioPlayer = try AVAudioPlayer(contentsOfURL: pathURL) } catch { audioPlayer = nil } audioPlayer?.prepareToPlay() audioPlayer.play() btnPause.hidden = false btnPlay.hidden = false三、音乐播放器创建
class AudioManager: NSObject, AVAudioPlayerDelegate { static let sharedManager = AudioManager() // singleton var audioPlayer: AVAudioPlayer! }然后在曲剧变量里实例化播放器
var audioPlayer = AudioManager.sharedManager.audioPlayer四、按钮事件绑定
1、音乐按钮播放音乐事件
func playWitnIndex(index: Int){ let music = arrMusicName[index] let path = NSBundle.mainBundle().pathForResource(music, ofType: "mp3") let pathURL=NSURL(fileURLWithPath: path!) do { audioPlayer = try AVAudioPlayer(contentsOfURL: pathURL) } catch { audioPlayer = nil } audioPlayer?.prepareToPlay() audioPlayer.play() btnPause.hidden = false btnPlay.hidden = false }这个方法吧button带过来,通过button的tag值判断所点击的按钮
2、播放按钮的点击事件
func play(){ audioPlayer.play() }3、暂停按钮的点击事件
func pause(){ audioPlayer.pause() }到这里,音乐播放器的基本功能就已经实现了,点击就会有音乐播放了,并且播放暂停功能都已经实现
五、音乐后台播放的实现
要实现后台音乐播放功能,还学要对音乐播放器设置一下
在viewDidLoad方法中添加一下代码:
UIApplication.sharedApplication().beginReceivingRemoteControlEvents() do { try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord) try AVAudioSession.sharedInstance().setActive(true) } catch { }只添加这个还不够,需要对工程进行设置 在info.plist添加Required background modes,具体如图:
这样,音乐播放器就实现了后台播放功能
六、音乐播放器锁屏音乐播放设置
添加setLockView方法,代码如下:
func setLockView(){ MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo = [ // 歌曲名称 MPMediaItemPropertyTitle:arrMusicName[btnIndex], // 演唱者 MPMediaItemPropertyArtist:"周杰伦", // 锁屏图片 MPMediaItemPropertyArtwork:MPMediaItemArtwork(image: UIImage(named: "aa.jpg")!), // MPNowPlayingInfoPropertyPlaybackRate:1.0, // 总时长 MPMediaItemPropertyPlaybackDuration:audioPlayer.duration, // 当前时间 MPNowPlayingInfoPropertyElapsedPlaybackTime:audioPlayer.currentTime ] }在viewDidLoad方法中调用这个方法:
self.setLockView()这样就实现了锁屏界面了按钮设置
锁屏按钮点击事件实现需要重写remoteControlReceivedWithEvent方法,代码如下:
override func remoteControlReceivedWithEvent(event: UIEvent?) { switch event!.subtype { case .RemoteControlPlay: // play按钮 audioPlayer.play() case .RemoteControlPause: // pause按钮 audioPlayer.pause() case .RemoteControlNextTrack: // next // ▶▶ self.btnIndex = self.btnIndex + 1 self.playWitnIndex(self.btnIndex) self.setLockView() break case .RemoteControlPreviousTrack: // previous // ◀◀ if self.btnIndex>0 { self.btnIndex = self.btnIndex - 1 self.playWitnIndex(self.btnIndex) self.setLockView() } break default: break } }七、外放问题的解决
此时,虽然功能都实现了,但是会发现音乐播放声音特别小,因为AVAudioPlayer默认是听筒播放,而不是扬声器播放 这里需要在播放器设置里添加如下设置代码
let session = AVAudioSession.sharedInstance() try session.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: AVAudioSessionCategoryOptions.DefaultToSpeaker)其他设置如图所示:
到这里,这个swift版的lxy杰伦情歌APP就大功告成了,文章最后附上项目源码(由于音乐文件太大,只保留前两首歌曲),希望大家喜欢:
项目源码下载地址