使用apple Music API 製作音樂軟體

今天使用api及解析Json字串的作業

api網址:https://itunes.apple.com/search?term=who&media=music&country=tw
(who=歌手)

已IU為例

從這邊可得到API回傳的JSON格式

trackName 是歌名
artworkUrl100 是圖片
previewUrl是音檔

所以我的model需建立與Json的欄位名稱一樣

import Foundation//Json 大分類
struct SearchResponse: Codable {
let resultCount : Int
let results: [StoreItem]
}
//Json 小分類,名稱需要與Json一樣
struct StoreItem: Codable {
let artistName: String
let trackName: String
let collectionName: String?
let previewUrl: URL
let artworkUrl100: URL
let trackPrice: Double?
let releaseDate: Date
let isStreamable: Bool?

var artworkUrl500: URL {

artworkUrl100.deletingLastPathComponent().appendingPathComponent("500x500bb.jpg")

}
}

前2個畫面

輸入歌手名稱至輸入匡
  1. 所以這部分會抓取textField的值
  2. 丟到API網址內湊成一個完整的API網址
  3. 使用API串回JSON格式
  4. 重整頁面
func getAPIData(){
//api網址
let urlString: String = "https://itunes.apple.com/search?term=\(singer)&media=music&country=tw"

if let url = URL(string: urlString) {

URLSession.shared.dataTask(with: url) { data, response , error in
if let data = data {
//解析Json格式
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
do {
let searchResponse = try decoder.decode(SearchResponse.self, from: data)
self.items = searchResponse.results
DispatchQueue.main.async {
self.tableView.reloadData()
}

} catch {
// show error
}
} else {
// show error
}
}.resume()
}
}

cell的內容

  1. cell筆數為API回傳的筆數
  2. 把回傳的內容顯示到畫面上
//cell 筆數
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return items.count
}
//cell內容
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SongListViewCell", for: indexPath) as! MusicTableViewCell
let item = items[indexPath.row]
cell.nameLabel.text = item.trackName
cell.photoImageView.image = UIImage(systemName: "music.house")
URLSession.shared.dataTask(with: item.artworkUrl100) { data, response , error in
if let data = data {
DispatchQueue.main.async {
cell.photoImageView.image = UIImage(data: data)
}
}
}.resume()
return cell
}

資料傳遞

1.抓取textField的值後,傳遞到一下頁組合API網址

//傳資料到下一頁-1
@IBAction func goList(_ sender: Any) {
//注意segue的ID命名
performSegue(withIdentifier: "GoResult", sender: nil)
}

//傳資料到下一頁-2
@IBSegueAction func goResult(_ coder: NSCoder) -> MusicTableViewController? {
let controller = MusicTableViewController(coder: coder)
//注意!!下一頁需宣告這個變數
controller?.singer = textField.text!
return controller
}

cell UI

  1. 建立TableViewCell
  2. 拉Label到TableViewCell內
  3. 就能編輯UILabel的資訊了
class MusicTableViewCell: UITableViewCell {@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!


override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
點選每一個歌,都能到下一頁試聽音樂

傳遞資料動作

  1. 接受頁面需建立init
  2. 第一頁拉完Segue後,執行下一頁的init,把要傳的值給丟過去
//第一頁
//傳資料到下一頁
@IBSegueAction func showDetail(_ coder: NSCoder) -> SongDetailViewController? {
//下一個需建一個init
if let row = tableView.indexPathForSelectedRow?.row {
return SongDetailViewController(coder: coder, item: items[row])
} else {
return nil
}
}
//下一頁
init?(coder: NSCoder, item: StoreItem) {
self.item = item
super.init(coder: coder)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

更新第三頁UI

    var item: StoreItem //定義給傳資料來的頁面nameLabel.text = item.trackName
URLSession.shared.dataTask(with: item.artworkUrl500) { data, response , error in
if let data = data {
DispatchQueue.main.async {
self.imageView.image = UIImage(data: data)
}
}
}.resume()
}

放音樂動作

  1. import AVFoundation
  2. var player: AVPlayer?
  3. 按按鈕就能放音樂囉
@IBAction func paly(_ sender: Any) {
player = AVPlayer(url: item.previewUrl)
player?.play()
}

Demo

附上我的GitHub

--

--