今回の内容

コード
Model
MusicDetailModel
struct MusicDetailModel{
let mediumImageUrl:String?
let title:String?
let artistName:String?
let label:String?
let itemCaption:String?
let playList:String?
}
import Alamofire
import SwiftyJSON
class AlamofireProcess{
private var privateMediumImageUrl:String?
private var privateTitle:String?
private var privateArtistName:String?
private var privateLabel:String?
private var privateItemCaption:String?
private var privatePlayList:String?
private var getMusicDataArray = [MusicDetailModel]()
}
extension AlamofireProcess{
public func getMusicData(searchKeyword:String?,completion: @escaping ([MusicDetailModel]?,Error?) -> Void){
guard let keyword = searchKeyword else { return }
let apikKey = "https://app.rakuten.co.jp/services/api/BooksCD/Search/20170404?format=json&artistName=\(keyword.urlEncoded)&applicationId=アプリID"
AF.request(apikKey, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON {[self] response in
switch response.result{
case .success:
let detailData = JSON(response.data as Any)
for dataCount in 0..<detailData["Items"].count{
getDataNilCheck(checkMediumImageUrl: detailData["Items"][dataCount]["Item"]["mediumImageUrl"].string,
checkTitle: detailData["Items"][dataCount]["Item"]["title"].string,
checkArtistName: detailData["Items"][dataCount]["Item"]["artistName"].string,
checkLabel: detailData["Items"][dataCount]["Item"]["label"].string,
checkItemCaption: detailData["Items"][dataCount]["Item"]["itemCaption"].string,
checkPlayList: detailData["Items"][dataCount]["Item"]["playList"].string)
getMusicDataArray.append(MusicDetailModel(mediumImageUrl: privateMediumImageUrl,
title: privateTitle,
artistName: privateArtistName,
label: privateLabel,
itemCaption: privateItemCaption,
playList: privatePlayList))
}
completion(getMusicDataArray, nil)
case .failure(let error):
completion(nil, error)
}
}
}
}
extension AlamofireProcess{
private func getDataNilCheck(checkMediumImageUrl:String?,checkTitle:String?,checkArtistName:String?,checkLabel:String?,checkItemCaption:String?,checkPlayList:String?){
if checkMediumImageUrl != nil{
privateMediumImageUrl = checkMediumImageUrl
}else{
privateMediumImageUrl = "noSign"
}
if checkTitle != nil{
privateTitle = checkTitle
}else{
privateTitle = "読み込みエラー"
}
if checkArtistName != nil{
privateArtistName = checkArtistName
}else{
privateArtistName = "読み込みエラー"
}
if checkLabel != nil{
privateLabel = checkLabel
}else{
privateLabel = "読み込みエラー"
}
if checkItemCaption != nil{
privateItemCaption = checkItemCaption
}else{
privateItemCaption = "読み込みエラー"
}
if checkPlayList != nil{
privatePlayList = checkPlayList
}else{
privatePlayList = "読み込みエラー"
}
}
}
extension String{
var urlEncoded:String{
let charset = CharacterSet.alphanumerics.union(.init(charactersIn: "/?-._~"))
let remove = removingPercentEncoding ?? self
return remove.addingPercentEncoding(withAllowedCharacters: charset) ?? remove
}
}
View

CollectionCustomCell
import UIKit
class CollectionCustomCell: UICollectionViewCell {
@IBOutlet weak var mediumImageView: UIImageView!
@IBOutlet weak var detailTextView: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func prepareForReuse() {
super.prepareForReuse()
mediumImageView.image = UIImage(named: "")
detailTextView.text = ""
}
}
MusicDetailViewController
import UIKit
import SDWebImage
class MusicDetailViewController: UIViewController {
@IBOutlet weak var mediumImageView: UIImageView!
@IBOutlet weak var playListView: UITableView!
public var playlistContentsArray = [String]()
public var imageURL:URL?
override func viewDidLoad() {
super.viewDidLoad()
mediumImageView.sd_setImage(with: imageURL, completed: nil)
playListView.register(UINib(nibName: "TableViewCustomCell", bundle: nil), forCellReuseIdentifier: "MusicNameCell")
playListView.dataSource = self
}
}
extension MusicDetailViewController:UITableViewDataSource{
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "PlayList"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return playlistContentsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MusicNameCell", for: indexPath) as! TableViewCustomCell
cell.musicNameLabel.text = playlistContentsArray[indexPath.row]
return cell
}
}
TableViewCustomCell
import UIKit
class TableViewCustomCell: UITableViewCell {
@IBOutlet weak var musicNameLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func prepareForReuse() {
super.prepareForReuse()
musicNameLabel.text = ""
}
}
Controller
- 取得した
playList
は曲名と曲名の間に###
が存在するString型
で取得されるので、tableView
に表示する為に、.components(separatedBy: "###")
を使用しています。
ViewController
import UIKit
import SDWebImage
class ViewController: UIViewController {
@IBOutlet weak var searchTextField: UITextField!
@IBOutlet weak var searchButton: UIButton!
@IBOutlet weak var resultCollectionView: UICollectionView!
private let collectionViewLayout = UICollectionViewFlowLayout()
private let alamofireProcess = AlamofireProcess()
private var cellContentsArray = [MusicDetailModel]()
override func viewDidLoad() {
super.viewDidLoad()
resultCollectionView.register(UINib(nibName: "CollectionCustomCell", bundle: nil), forCellWithReuseIdentifier: "MusicDetailCell")
resultCollectionView.delegate = self
resultCollectionView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
collectionViewLayout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
resultCollectionView.collectionViewLayout = collectionViewLayout
}
@IBAction func artistNameSearch(_ sender: UIButton) {
if searchTextField.text?.isEmpty != true{
alamofireProcess.getMusicData(searchKeyword: searchTextField.text) { result, error in
if error != nil{
print(error.debugDescription)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {[self] in
cellContentsArray = result!
resultCollectionView.reloadData()
}
}
}
}
}
extension ViewController:UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let musicDetailVC = MusicDetailViewController()
musicDetailVC.modalPresentationStyle = .automatic
musicDetailVC.playlistContentsArray = []
musicDetailVC.playlistContentsArray = (cellContentsArray[indexPath.row].playList?.components(separatedBy: "###"))!
musicDetailVC.imageURL = URL(string: cellContentsArray[indexPath.row].mediumImageUrl!)
self.present(musicDetailVC, animated: true, completion: nil)
}
}
extension ViewController:UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cellContentsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MusicDetailCell", for: indexPath) as! CollectionCustomCell
cell.mediumImageView.sd_setImage(with: URL(string: cellContentsArray[indexPath.row].mediumImageUrl!))
cell.detailTextView.text = """
タイトル:
\(cellContentsArray[indexPath.row].title ?? "読み込みエラー")
アーティスト:
\(cellContentsArray[indexPath.row].artistName ?? "読み込みエラー")
レーベル:
\(cellContentsArray[indexPath.row].label ?? "読み込みエラー")
説明文:
\(cellContentsArray[indexPath.row].itemCaption ?? "読み込みエラー")
"""
return cell
}
}
extension ViewController:UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width / 2 - 10, height: collectionView.frame.height / 2 - 10)
}
}
終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。