iTunesMusic App developed note

Alice Fang
2 min readJul 8, 2021

在此簡單記錄一下開發過程遇到的問題與參考的資料,GitHub上有demo影片,這邊就不重複放囉~

App demo/GitHub:

在searchBar搜尋,下方會跳出相對應的結果,點擊play button會播放previewUrl music

APP content:

Defined static shared, call function by shared
Defined function with completion
Get API data, decode to JSON format

App function detail:

UISearchResultsUpdating:

URLComponents, URLQueryItem:
當QueryItem不只一項時,可以用component.queryItems來新增

var queries = [String:String]()
queries["term"] = "告五人"
queries["media"] = "music"
queries["country"] = "tw"
...var component = URLComponents(url: searchUrl, resolvingAgainstBaseURL: true)!
component.queryItems = queries.map{
URLQueryItem(name: $0.key, value: $0.value)
}

completion & Result type:
使用Result type可以讓Error handling更完善
下面以fetchImageWithURL為例子,completion(.success(image))傳出成功的image,接收時先用switch case確認result,若是成功就可以取得image

click cell’s button to do something:
若是在xib拉button action會無法判斷是哪個cell button被觸發,所以先做click cell and play music

查了發現以下方法可行,已修正(demo影片未更新)
cell button edit tag and addTarget, click button will trigger #selector func.
Use tag to recognized which cell’s button been clicked
另外因為dequeueReusableCell的特性,在cellForItemAt要設定button image,不然上下滑動cell後image會跑掉(例如:播放中的stop image被改成play image)
currentPlayingItemButton是正在播放音樂的button,音樂播完後要改nil

override func collectionView(_ collectionView: UICollectionView, cellForItemAt......//設定button tag, addTarget
cell.playButton.tag = indexPath.row
cell.playButton.addTarget(self, action: #selector(playButtonGroupAction(sender:)), for: .touchUpInside)
...//設定button image
if cell.playButton.tag == currentPlayingItemButton?.tag{
cell.playButton.setImage(UIImage(systemName: "stop"), for: .normal)
}else{
cell.playButton.setImage(UIImage(systemName: "play"), for: .normal)
}

play music:
AVFoundation
let player = AVPlayer()這個要設在global area, 不能設在func裡面,func一結束就會被釋放了,會造成音樂連一秒都沒有播放

class iTunesController{...
let player = AVPlayer()
...func playPreviewURL(_ url:URL){
let playerItem = AVPlayerItem(url: url)
player.replaceCurrentItem(with: playerItem)
player.play()
}

do something when play music done:
用NotificationCenter設定addObserver for AVPlayerItemDidPlayToEndTime
音樂播放完畢後,我想把button image從stop改成play,不知道為什麼都改不動(用DispatchQueue.main.async包起來也不行),目前先用reloadData(有成功,但畫面會閃一下),可能要研究一下DispatchQueue

NotificationCenter.default.addObserver(forName: Notification.Name.AVPlayerItemDidPlayToEndTime, object: nil, queue: .main) { (notification) in
//self.currentPlayingItemButton?.setImage(UIImage(systemName: "play"), for: .normal)
self.currentPlayingItemButton = nil
self.collectionView.reloadData()
}

Auto Layout:
好像有東西沒設定好(需要再研究),重畫cell時會跑出一大堆LayoutConstraints debug message,可以暫時用這行關掉

//Hide Autolayout Warning
UserDefaults.standard.set(false,forKey:"_UIConstraintBasedLayoutLogUnsatisfiable")

Reference:

--

--

Alice Fang

你不需要很厲害才能開始,但你需要開始才能很厲害