使用apple Music API 製作音樂軟體
Published in
9 min readApr 20, 2022
今天使用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個畫面
- 所以這部分會抓取textField的值
- 丟到API網址內湊成一個完整的API網址
- 使用API串回JSON格式
- 重整頁面
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的內容
- cell筆數為API回傳的筆數
- 把回傳的內容顯示到畫面上
//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
- 建立TableViewCell
- 拉Label到TableViewCell內
- 就能編輯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
}}
傳遞資料動作
- 接受頁面需建立init
- 第一頁拉完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()
}
放音樂動作
- import AVFoundation
- var player: AVPlayer?
- 按按鈕就能放音樂囉
@IBAction func paly(_ sender: Any) {
player = AVPlayer(url: item.previewUrl)
player?.play()
}
Demo
附上我的GitHub