#15 實現Custom Table View 跟 iTune Json串接
這次是利用客製化的Table View表格來顯示由網路抓取itune的資料,圖示如下:
這次主要需要兩個功能,一個是把itune歌曲資料放到表格上,另外一個是點選表格之後會播放音樂
StoryBoard畫面如下:
一個動態表格,一個cell,裡面放入圖片跟三個Label,分別為歌手、專輯、歌曲
接下來就是測試Json資料,網址如下:
https://itunes.apple.com/search?media=music&term=歌手名稱
如果只是要特定人的Json資料,資訊可以打得更完全,但這次要實現的是搜尋不同歌手的資料,因此歌手名稱做為一個變數
接下來的程式碼如下:
struct 部分,需要對應Json的參數名稱作為property,一個字錯誤就抓不到資料,itune下載的json資料是一個大括號,兩個property,一個是resultCount,一個是results的陣列,results的陣列裡面又含了約30幾筆資料,我只截取自己想要的封面圖片(artworkUrl100)、音樂預覽(previewUrl)、歌手(artistName)、專輯名稱(ollectionName)、歌曲名稱(trackName)
import Foundationstruct ituneMusic : Codable {var resultCount : Intvar results : [storeItem]}struct storeItem: Codable {var artistName: String = ""var collectionName: String = ""var trackName : String = ""var previewUrl : URL?var artworkUrl100: URL?}
接下來是ViewController的部分,設定四個變數,一個是items,型別為剛剛struct裡面storeItem的型別到時候擷取資料後,會把資料儲存進去,另外一個是歌手的字串變數,然後播放音樂用的avplayer以及searchBar的collection,然後把接收資料的function拉出來寫一個readUrl的function,table row的部分就是看到時候接收到幾筆資料,就會有幾個row,然後tableView的部分就顯示圖片、名稱、歌手等等的資料,別且把型別轉成自訂的cell,最後didselected的設定,就是點選之後會播放音樂,最重要的是搜尋的功能,需要設定delegate,這邊我是直接拉segue到controller並且選擇delegate,然後在class的最外面用extension的方式新增一個遵循searchBarDelegate的protocol,這個在打完名字按搜尋的時候會觸發程式,因此把剛剛的readUrl function丟進去就大功告成了:
import UIKit
import AVKitclass MusiceTableViewController: UITableViewController {
var items: [storeItem] = []
var singer: String = ""
var player : AVPlayer?
@IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
}
func readUrl(){
singer = searchBar.text!
let urlString = URLComponents(string: "https://itunes.apple.com/search?media=music&term=\(singer)")
if let url = urlString?.url {
URLSession.shared.dataTask(with: url){ data, response, error in
if let data = data {
let decoder = JSONDecoder()
do {
let searchResponse = try decoder.decode(ituneMusic.self, from: data)
self.items = searchResponse.results
DispatchQueue.main.async { self.tableView.reloadData() }
for _ in self.items.indices {
}
} catch {
print(error as Any)
}
} else {
print(error as Any)
}
}.resume()
}
}override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return items.count
}override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ituneMusic", for: indexPath) as! MusicTableViewCell
cell.albumLabel.text = items[indexPath.row].collectionName
cell.singerLabel.text = items[indexPath.row].artistName
cell.songLabel.text = items[indexPath.row].trackName
if let imageUrl = items[indexPath.row].artworkUrl100 {
let task = URLSession.shared.dataTask(with: imageUrl) { data, response, error in
if let data = data {
DispatchQueue.main.async {
cell.albumImage.image = UIImage(data: data)
}
}
}.resume()
}// Configure the cell...return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// var previewViewController = AVPlayerViewController()
if let previewUrl = items[indexPath.row].previewUrl {
player = AVPlayer(url: previewUrl)
// previewViewController.player = player
}
player?.play()// present(previewViewController, animated: true){
// previewViewController.player?.play()
// }
tableView.deselectRow(at: indexPath, animated: false) }
}extension MusiceTableViewController: UISearchBarDelegate{
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
readUrl()
searchBar.resignFirstResponder()
}
}
接下來是tableViewCell的程式碼,其實只是把剛剛的圖片、label全丟拉到cell裡面就可以:
import UIKitclass MusicTableViewCell: UITableViewCell {@IBOutlet weak var albumImage: UIImageView!
@IBOutlet weak var singerLabel: UILabel!
@IBOutlet weak var albumLabel: UILabel!
@IBOutlet weak var songLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}}
GitHub: