作業#31 模仿 iOS 的 Music App 製作情歌點唱機
原本做完上一個作業想說繼續複習一下前面的漸層。。。結果Peter說 你還沒有做過 Music App 吧? Peter金口一開,只能先放下一切事物盡力做出來了!一開始的時候還蠻順利的,但是到了Slider 跟 音樂時間時就大卡關了。最後還是參考了學長姐的文章才順利做出來。。。
接下來跟大家分享我做好的Music App!
這是我拉的介面,等之後對TableView熟悉後 希望可以再加入一頁是TableView的音樂列表。
首先拉好元件的Outlet跟Action
這次的Action比較多,用綠色代表是有Outlet跟Action的;紅色就是只有Outlet。
宣告類別,常數、變數
宣告的變數跟常數,註解是各自的功用。
宣告的struct以及struct內容。
接下來就是比較複雜的Func
先從比較簡單的講起來
如何播放音樂以及更新畫面
這邊可以參考Peter的文章有詳細的講解,上面也有每個程式碼的註解跟功能。
// 播放音樂func playMusic(){// 宣告一個fileUrl來呼叫音樂的檔案let fileUrl = Bundle.main.url(forResource: allmusic[musicIndex].music , withExtension: "mp4")!// 儲存播放音樂的playerItemplayerItem = AVPlayerItem(url: fileUrl)// 播放音樂的playerplayer.replaceCurrentItem(with: playerItem)// 播放音樂player.play()}
更新畫面
這也是比較基礎的。跟以前做的大同小異!沒有什麼困難的!
// 更新歌曲、歌手、畫面圖片func updateUI(){musicNameLB.text = allmusic[musicIndex].musicNamesingerLB.text = allmusic[musicIndex].singermusicPicIV.image = UIImage(named: allmusic[musicIndex].musicPic)// starTimeLB.text = String(player.currentTime().seconds)}
設定Symbols圖示大小以及圖片
我將它做成一個回傳是UIImage的Func可以設定你要的Symbols以及大小。
之後只要宣告.setImage就可以輕鬆的設定你想要的Symbols跟大小了。
//粗體的就是Func非常方便!
stopMusicButton.setImage(setbuttonImage(systemName: "pause.fill", pointSize: 30), for: .normal)
// 設定Button圖示大小跟圖案func setbuttonImage(systemName:String,pointSize: Int)-> UIImage?{// 設定一個圖示以及他的長寬let sfsymbol = UIImage.SymbolConfiguration(pointSize: CGFloat(pointSize), weight: .bold,scale: .large)// 設定圖片名字,跟他的出處let sfsymbolImage = UIImage(systemName: systemName, withConfiguration: sfsymbol)// 回傳return sfsymbolImage}
上\下一首歌的Func
這邊也是比較簡單的部分!只要讓musicIndex +1就可以跳到下一首。也要先確認shuffleIndex是否有開啟有的話就要用Int.random(in: 0…allmusic.count — 1)亂數曲歌。
// 播放下一首歌func playNextSound(){// 如果隨機播放是打開的if shuffleIndex == 1{// 就用亂數播歌musicIndex = Int.random(in: 0...allmusic.count - 1)updateUI()playMusic()updateMusciUI()}else{// 如果不是就是照列表播歌musicIndex += 1if musicIndex < allmusic.count{updateUI()playMusic()updateMusciUI()}else{musicIndex = 0updateUI()playMusic()updateMusciUI()}}}
確認Slider的最大秒數 最大秒數轉成分鐘+秒數的Func
接下來就是比較困難的地方了。。。我也是參考了許多學長姐的文章最終才完成的!雖然有些真的還是不太清楚。但是至少那個程式碼的功用!
讓Slider跟著音樂跑的Func
要讓Slider按照著秒數跑真的是不簡單,我大概看了半天的我還是不太理解他的運作。我覺得是這次作業最困難的地方!再好好研究研究。。。
// 播放幾秒的Funcfunc nowPlayTime(){// 播放的計數器從1開始每一秒都在播放player.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1), queue: DispatchQueue.main, using: { (CMTime) in// 如果音樂要播放if self.player.currentItem?.status == .readyToPlay{// 就會得到player播放的時間let currenTime = CMTimeGetSeconds(self.player.currentTime())// Slider移動就會等於currenTime的時間self.playTimeSlider.value = Float(currenTime)// 顯示播放了幾秒self.starTimeLB.text = self.timeShow(time: currenTime)}})}
確認音樂結束後下一首從頭播放
這邊也是偏困難的地方,那時候做好前面後看到slider開始跟著動很開心。但是發現一首歌結束後除非自己按下一首不然他不會自動換歌。最後又研究了許久。才知道要加入這個Func。
/ 確認音樂結束func musicEnd(){// 叫出 NotificationCenter.default.addObserver來確認音樂是否結束NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: .main) { (_) in// 如果結束有打開repeatBool 就會從頭播放if self.repeatBool{let musicEndTime: CMTime = CMTimeMake(value: 0, timescale: 1)self.player.seek(to: musicEndTime)self.player.play()}else{// 如果結束沒有打開repeatBool就會撥下一首歌self.playNextSound()}}}
將Func套入到@IBAction裡
暫停、播放、下一首、Slider調音樂到幾秒
這邊是比較簡單的部分。只是下面的Slider也是有點困難的地方。
可以看到我也是用比較簡單易懂得寫法使用index等於1或0來控制圖案。
重複播放\隨機播放
這邊也比較簡單,因為都寫在Func裡,這邊只要設定按下去後變更的圖示就好。
看到Slider會動的時候真的很開心!
最後是加入MV
我這邊是使用 AVPlayerViewController來播放MV好處是,不用設定什麼!帥哥學長教我用override func prepare(for segue: UIStoryboardSegue, sender: Any?)來播放!我覺得非常方便!
// 播放當前在播放的東西override func prepare(for segue: UIStoryboardSegue, sender: Any?) {// 讓影片播放跟主頁一樣let MyAVPlayerVC = segue.destination as! MyAVPlayerViewController// 播放MyAVPlayerVC.player = player}