#iTunesAPI
iTunesAPIを利用することでiTunes内の本、映画、ポッドキャスト、音楽、ミュージックビデオ、オーディオブック、テレビ番組などの情報を取得できます。今回はその中でも音楽の視聴音源を用いて音楽視聴アプリを作ってみました。
iTunesAPIのドキュメントに関して
##リクエスト例
例としてoneokrockの情報を取得してみます。
リクエストURLは以下のようになります。
https://itunes.apple.com/search?term=\oneokrock&entity=song&contry=jp
##レスポンス
上記のURLを入力すると以下のような.txtファイルがダウンロードされる
(少々長いのでresultCount2つまでを表示)
JSON Pretty Linterを用いて整形しました。
{
resultCount:50
results:[
0:{
wrapperType:track
kind:song
artistId:252239625
collectionId:605688804
trackId:605689011
artistName:ONE OK ROCK
collectionName:Jinsei × Boku =
trackName:Clock Strikes
collectionCensoredName:Jinsei × Boku =
trackCensoredName:Clock Strikes
artistViewUrl:https://music.apple.com/us/artist/one-ok-rock/252239625?uo=4
collectionViewUrl:https://music.apple.com/us/album/clock-strikes/605688804?i=605689011&uo=4
trackViewUrl:https://music.apple.com/us/album/clock-strikes/605688804?i=605689011&uo=4
previewUrl:https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/af/6f/df/af6fdfd5-a32c-e794-ed20-e2e20c043981/mzaf_14716866606323246628.plus.aac.p.m4a
artworkUrl30:https://is4-ssl.mzstatic.com/image/thumb/Music125/v4/db/43/0a/db430aad-9319-2f7b-005c-8646e7f388a8/source/30x30bb.jpg
artworkUrl60:https://is4-ssl.mzstatic.com/image/thumb/Music125/v4/db/43/0a/db430aad-9319-2f7b-005c-8646e7f388a8/source/60x60bb.jpg
artworkUrl100:https://is4-ssl.mzstatic.com/image/thumb/Music125/v4/db/43/0a/db430aad-9319-2f7b-005c-8646e7f388a8/source/100x100bb.jpg
collectionPrice:13.99
trackPrice:1.29
releaseDate:2013-03-06T12:00:00Z
collectionExplicitness:notExplicit
trackExplicitness:notExplicit
discCount:1
discNumber:1
trackCount:13
trackNumber:5
trackTimeMillis:235347
country:USA
currency:USD
primaryGenreName:Rock
isStreamable:true
}
1:{
wrapperType:track
kind:song
artistId:252239625
collectionId:1176157333
trackId:1176157730
artistName:ONE OK ROCK
collectionName:Ambitions
trackName:Take What You Want (feat. 5 Seconds of Summer)
collectionCensoredName:Ambitions
trackCensoredName:Take What You Want (feat. 5 Seconds of Summer)
artistViewUrl:https://music.apple.com/us/artist/one-ok-rock/252239625?uo=4
collectionViewUrl:https://music.apple.com/us/album/take-what-you-want-feat-5-seconds-of-summer/1176157333?i=1176157730&uo=4
trackViewUrl:https://music.apple.com/us/album/take-what-you-want-feat-5-seconds-of-summer/1176157333?i=1176157730&uo=4
previewUrl:https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/4e/cc/30/4ecc300e-a281-2d0c-1fb6-72886e3f9bc5/mzaf_6734311677989074101.plus.aac.p.m4a
artworkUrl30:https://is3-ssl.mzstatic.com/image/thumb/Music125/v4/ca/fc/a8/cafca8f8-f563-ab15-5873-974092810637/source/30x30bb.jpg
artworkUrl60:https://is3-ssl.mzstatic.com/image/thumb/Music125/v4/ca/fc/a8/cafca8f8-f563-ab15-5873-974092810637/source/60x60bb.jpg
artworkUrl100:https://is3-ssl.mzstatic.com/image/thumb/Music125/v4/ca/fc/a8/cafca8f8-f563-ab15-5873-974092810637/source/100x100bb.jpg
collectionPrice:9.99
trackPrice:1.29
releaseDate:2017-01-11T12:00:00Z
collectionExplicitness:notExplicit
trackExplicitness:notExplicit
discCount:1
discNumber:1
trackCount:14
trackNumber:14
trackTimeMillis:243274
country:USA
currency:USD
primaryGenreName:Rock
isStreamable:true
}
//以下省略
##今回アプリで用いる情報とライブラリ
###artistName
アーティスト名
###trackCensoredName
曲名
###previewUrl
視聴音源URL
###artworkUrl100
アルバムジャケット
###ライブラリの導入
Podfileに以下をインストール
pod 'SwiftyJSON',
pod 'Alamofire',
pod 'SDWebImage
##コーディング
役割ごとにModel,View,Controllerに分けてコーディングを行う
##View
##Model
model.swift
import Foundation
import SwiftyJSON
import Alamofire
protocol MusicProtocol {
func catchData(count:Int)
}
class MusicModel{
var artistNameArray = [String]()
var trackCensoredNameArray = [String]()
var previewUrlArray = [String]()
var artworkUrl100Array = [String]()
var musicDelegate:MusicProtocol?
//JSON解析
func setData(resultCount:Int,encodeUrlString:String){
//Alamfireによる通信
AF.request(encodeUrlString, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { (response) in
//responseの値表示
print("response:",response)
//一旦配列に入っているものすべてを削除する(蓄積防止)
self.artistNameArray.removeAll()
self.trackCensoredNameArray.removeAll()
self.previewUrlArray.removeAll()
self.artworkUrl100Array.removeAll()
switch response.result{
case .success:
do {
let json:JSON = try JSON(data: response.data!)
for i in 0...resultCount-1{
//もしartistNameがnilだったら
if json["results"][i]["artistName"].string == nil{
print("ヒットしませんでした")
return
}
self.artistNameArray.append(json["results"][i]["artistName"].string!)
self.trackCensoredNameArray.append(json["results"][i]["trackCensoredName"].string!)
self.previewUrlArray.append(json["results"][i]["previewUrl"].string!)
self.artworkUrl100Array.append(json["results"][i]["artworkUrl100"].string!)
}
//全てのデータを取得している状態
self.musicDelegate?.catchData(count:1)
} catch {
}
break
case .failure(_):break
}
}
}
}
##Controller
controller.swift
import UIKit
import SDWebImage
import AVFoundation
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate,MusicProtocol {
@IBOutlet weak var searchTextField: UITextField!
@IBOutlet weak var musicTableView: UITableView!
var musicModel = MusicModel()
var player:AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
musicTableView.delegate = self
musicTableView.dataSource = self
searchTextField.delegate = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
//tableViewDelegateによるデリゲートメソッド
//returnカウントの数だけcellForRowAtが呼ばれる
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return musicModel.artistNameArray.count
}
//tableViewDelegateによるデリゲートメソッド
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = musicTableView.dequeueReusableCell(withIdentifier: "musicCell", for: indexPath)
let artWorkImageView = cell.contentView.viewWithTag(1) as! UIImageView
let musicNameLabel = cell.contentView.viewWithTag(2) as! UILabel
let artistNameLabel = cell.contentView.viewWithTag(3) as! UILabel
//写真、音楽名、アーティスト名の格納
artWorkImageView.sd_setImage(with: URL(string: musicModel.artworkUrl100Array[indexPath.row]), completed: nil)
musicNameLabel.text = musicModel.trackCensoredNameArray[indexPath.row]
artistNameLabel.text = musicModel.artistNameArray[indexPath.row]
//楽曲再生ボタンの作成
let musicPlayButton = UIButton(frame: CGRect(x: 35, y: 21, width: 130, height: 130))
musicPlayButton.setImage(UIImage(named:"play"), for: .normal)
//ボタンを押したとき
musicPlayButton.addTarget(self, action: #selector(playButtonTap(_:)), for:.touchUpInside)
musicPlayButton.tag = indexPath.row
//セルにmusicButtonを追加(StoryBoardにないから)
cell.contentView.addSubview(musicPlayButton)
return cell
}
//ボタンをタップした時
@objc func playButtonTap(_ sender:UIButton){
//音楽を止める
if player?.isPlaying == true{
player?.stop()
}
//sender.tagはindexPath.rowすなわちplayButton.tagとい一緒
let url = URL(string: musicModel.previewUrlArray[sender.tag])
downLoadMusicURL(url: url!)
}
//リターンが押されたときにキーボードを閉じる
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
//キーボードを閉じる
refleshData()
textField.resignFirstResponder()
return true
}
//セルの高さ
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 170
}
//ダウンロードメソッド
func downLoadMusicURL(url:URL){
var downloadTask:URLSessionDownloadTask
downloadTask = URLSession.shared.downloadTask(with: url, completionHandler: { (url, response, error) in
self.play(url: url!)
})
downloadTask.resume()
}
//音楽再生メソッド
func play(url:URL){
do {
player = try AVAudioPlayer(contentsOf: url)
player?.prepareToPlay()
player?.volume = 1.0
player?.play()
} catch let error as NSError {
print(error.description)
}
}
//MusicProtocolによるデリゲートメソッド
func catchData(count: Int) {
if count == 1{
musicTableView.reloadData()
}
}
func refleshData(){
//テキストフィールドの中にアーティスト名が入ってたらアーティスト名を用いてitunesAPIを用いる
if searchTextField.text?.isEmpty != nil{
let urlString = "https://itunes.apple.com/search?term=\(String(describing:searchTextField.text!))&entity=song&contry=jp"
//urlStringをエンコードする
let encodeUrlString:String = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
//委任
musicModel.musicDelegate = self
musicModel.setData(resultCount: 50, encodeUrlString: encodeUrlString)
//キーボードを閉じる
searchTextField.resignFirstResponder()
}
}
@IBAction func searchAction(_ sender: Any) {
refleshData()
}
}
デモ動画
アルバムジャケットの上に配置した再生ボタンを押せば音源が流れる仕様になっています