3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

株式会社やどかり & 株式会社ネッコスAdvent Calendar 2021

Day 24

【Swift】APIでサッカー選手検索してみた②

Posted at

はじめに

いやあ〜クリスマスですね、思い出に残っているプレゼントはありますか?
僕は小学生の時にサンタさんにもらったガリューンです。(わかる人いますかねっ笑)
garyuun.jpg
電脳冒険記ウェブダイバーってアニメのキャラなんです、もう内容は一つも覚えてないですが。。。
このおもちゃ、テレビに繋いでゲームができるんですよ!
あの当時、おもちゃがテレビと連動するなんて画期的すぎて、Oka少年は夢中でした。
やっぱりプレゼントっていいですね、クリスマスに限らずいつでもプレゼント募集してますので、皆さんお待ちしております!

はい、では前回に引き続き、API-FOOTBALLを使っていこうと思います。

今日のGOAL

完全に自己満で色んな選手のプレーデータを見たいので、
今日は、前回作成した選手検索画面から詳細画面に遷移して色々表示していこうと思います。

GOALまでの大雑把な道筋

①前回の検索画面にPickerViewを実装
②詳細画面へ検索結果の値を渡して画面遷移
③詳細画面にScrollViewを実装
④詳細画面でAPI通信し表示

①前回の検索画面にPickerViewを実装

前回の検索画面はSeasonやリーグ名をベタ打ちしてました。
なので、まず選択肢を配列で用意してそれをPickerViewで表示させます。

ViewController.swift
// 前回作成したTextField=>これにPickerViewを実装
    @IBOutlet weak var seasonTextField: UITextField!
    @IBOutlet weak var leagueTextField: UITextField!

// 各TextField用にUIPickerViewをインスタンス化
    var seasonPickerView = UIPickerView()
    var leaguePickerView = UIPickerView()

// SeasonとLeagueの選択肢を配列で作成    
    var seasonArray = ["1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012","2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024"]
    var leagueArray = ["Liga", "League1", "Premier", "SerieA", "Eredivisie"]

    override func viewDidLoad() {
        super.viewDidLoad()
// configurePickerView()を呼び出し
        configurePickerView()
    }

    func configurePickerView() {
// UIPickerViewの各インスタンスのデリゲート先にself(=このViewController自身)を指定
        seasonPickerView.delegate = self
        seasonPickerView.dataSource = self
        leaguePickerView.delegate = self
        leaguePickerView.dataSource = self
// TextFieldのinputView(キーボードをカスタマイズ)にUIPickerViewを設定
        seasonTextField.inputView = seasonPickerView      
        leagueTextField.inputView = leaguePickerView
    }

// ViewControllerにUIPickerViewプロトコルを準拠させる
extension ViewController: UIPickerViewDelegate {
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// PickerViewで選択時の挙動を設定。(今回はtextFieldに格納させる処理)
        if pickerView == seasonPickerView {
            seasonTextField.text = seasonArray[row]
        } else {
            leagueTextField.text = leagueArray[row]
        }
    }
}

// ViewControllerにUIPickerViewプロトコルを準拠させる
extension ViewController: UIPickerViewDataSource {
// PickerViewに表示する項目数を設定
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

// PickerViewの選択肢数を設定    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
// PickerViewがSeasonか、Leagueかで分岐
        if pickerView == seasonPickerView {
            return seasonArray.count
        } else {
            return leagueArray.count
        }
    }

// PickerViewに表示する選択肢の中身を設定    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if pickerView == seasonPickerView {
            return seasonArray[row]
        } else {
            return leagueArray[row]
        }
    }
}

Simulator Screen Shot - iPhone 13 - 2021-12-27 at 00.12.41.png
Simulator Screen Shot - iPhone 13 - 2021-12-27 at 00.12.47.png
上手いこといってますね。Okay~

②詳細画面へ検索結果の値を渡して画面遷移

詳細画面に画面遷移をしたいのですが、
詳細画面では、playerIDとSeasonをパラメータにしてAPIリクエストを行いたいです。
なので、その2つの値も画面遷移と一緒に渡したいです。
ViewControllerにUIButtonを設置してIBActionを設定します。

まず、詳細画面のViewControllerをStoryBoardで作成します。
前画面から渡ってきた値を受け取る用の変数を用意しておきます。

DetailViewController.swift
class DetailViewController: UIViewController {
    var playerID: String = ""
    var season: String = ""
}

遷移元のViewControllerで値を渡して遷移する処理を実装。

ViewController.swift
    @IBAction func moveToDetailVC(_ sender: Any) {
// storyBoardをインスタンス化 
        let storboard = self.storyboard!
// 遷移先のViewControllerをインスタンス化(今回はDetailViewControllerを作成)
// withIdentifierに遷移先のViewControllerのstoryBoardIDを設定
        let detailVC = storboard.instantiateViewController(withIdentifier: "detailVC") as! DetailViewController
// 先ほど用意したDetailViewControllerの変数に値を格納
        detailVC.playerID = self.playerID
        detailVC.season = self.seasonText
// モーダル遷移(.fullScreenで全画面表示)
        detailVC.modalPresentationStyle = .fullScreen
        self.present(detailVC, animated: true, completion: nil)
    }

これで値を渡せます!!

③詳細画面にScrollViewを実装

今回は、表示させたい項目が多くて画面に収まりきらないのでScrollViewを使用して、上下スクロールできるようにします。
かなり端折りますが、簡単に言うと下記の手順で設定。
1.ViewControllerにScrollViewを追加
(SafeAreaに対してConstraintsを上下左右0)
2.ScrollViewの下にUIViewを追加
(ScrollView配下のContentLayoutGuideに対してConstraintsを上下左右0、FrameLayoutGuideに対してEqualWidthを設定)
3.UIViewの高さを表示したい内容が収まる高さに設定

スクリーンショット 2021-12-27 0.23.06.png

④詳細画面でAPI通信し表示

前の画面から受け取ったplayerIDとSeasonをパラメータに渡して、選手のデータを取得します。
API通信の処理は前回と全く同じなので、前回分を見ていただけたらと思います。

DetailViewController.swift
import UIKit
import Foundation
import SwiftyJSON
import AlamofireImage

class DetailViewController: UIViewController {

// 表示させたい項目をIBOutlet接続。
    @IBOutlet weak var playerImage: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var teamLabel: UILabel!
    @IBOutlet weak var seasonLabel: UILabel!
    @IBOutlet weak var goalLabel: UILabel!
    @IBOutlet weak var shootsLabel: UILabel!
    @IBOutlet weak var onTargetLabel: UILabel!
    @IBOutlet weak var assistsLabel: UILabel!
    @IBOutlet weak var totalPassesLabel: UILabel!
    @IBOutlet weak var keyPassLabel: UILabel!
    @IBOutlet weak var passAccuracyLabel: UILabel!
    @IBOutlet weak var totalTacklesLabel: UILabel!
    @IBOutlet weak var interceptionLabel: UILabel!
    @IBOutlet weak var dribblesLabel: UILabel!
    @IBOutlet weak var dribblesSuccessLabel: UILabel!
    @IBOutlet weak var playedGamesLabel: UILabel!
    @IBOutlet weak var playedMinutesLabel: UILabel!
    @IBOutlet weak var duelsLabel: UILabel!
    @IBOutlet weak var duelsWonLabel: UILabel!
    
// 前画面から値を受け取る用の変数
    var playerID: String = ""
    var season: String = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        loadData()
    }
    
    func loadData() {
        let headers = [
            "x-rapidapi-host": "api-football-v1.p.rapidapi.com",
            "x-rapidapi-key": "71d5d7e247msh2e0b3ec472fd452p1b9c2fjsnacb7856b6d30"
        ]

        let request = NSMutableURLRequest(url: NSURL(string: "https://api-football-v1.p.rapidapi.com/v3/players?id=\(self.playerID)&season=\(self.season)")! as URL,
                                                cachePolicy: .useProtocolCachePolicy,
                                            timeoutInterval: 10.0)
        request.httpMethod = "GET"
        request.allHTTPHeaderFields = headers

        let session = URLSession.shared
        let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
                if let json = try? JSON(data: data!) {
                    print("datadata", json["response"])
                    let name = json["response"][0]["player"]["name"]
                    let team = json["response"][0]["statistics"][0]["team"]["name"]
                    let season = json["response"][0]["statistics"][0]["league"]["season"]
                    let playedGames = json["response"][0]["statistics"][0]["games"]["appearences"]
                    let playedMinutes = json["response"][0]["statistics"][0]["games"]["minutes"]
                    let goal = json["response"][0]["statistics"][0]["goals"]["total"]
                    let shoots = json["response"][0]["statistics"][0]["shots"]["total"]
                    let onTarget = json["response"][0]["statistics"][0]["shots"]["on"]
                    let assists = json["response"][0]["statistics"][0]["goals"]["assists"]
                    let passes = json["response"][0]["statistics"][0]["passes"]["total"]
                    let keyPasses = json["response"][0]["statistics"][0]["passes"]["key"]
                    let passesAccuracy = json["response"][0]["statistics"][0]["passes"]["accuracy"]
                    let totalTackles = json["response"][0]["statistics"][0]["tackles"]["total"]
                    let interceptions = json["response"][0]["statistics"][0]["tackles"]["interceptions"]
                    let dribbles = json["response"][0]["statistics"][0]["dribbles"]["attempts"]
                    let dribblesSuccess = json["response"][0]["statistics"][0]["dribbles"]["success"]
                    let duels = json["response"][0]["statistics"][0]["duels"]["total"]
                    let duelsWon = json["response"][0]["statistics"][0]["duels"]["won"]
                    let imageURL = json["response"][0]["player"]["photo"]
                    let url = NSURL(string: imageURL.stringValue)
                    DispatchQueue.main.async() { () -> Void in
                        self.nameLabel.text = name.stringValue
                        self.teamLabel.text = team.stringValue
                        self.seasonLabel.text = season.stringValue
                        self.playedGamesLabel.text = playedGames.stringValue
                        self.playedMinutesLabel.text = playedMinutes.stringValue
                        self.goalLabel.text = goal.stringValue
                        self.shootsLabel.text = shoots.stringValue
                        self.onTargetLabel.text = onTarget.stringValue
                        self.assistsLabel.text = assists.stringValue
                        self.totalPassesLabel.text = passes.stringValue
                        self.keyPassLabel.text = keyPasses.stringValue
                        self.passAccuracyLabel.text = passesAccuracy.stringValue
                        self.totalTacklesLabel.text = totalTackles.stringValue
                        self.interceptionLabel.text = interceptions.stringValue
                        self.dribblesLabel.text = dribbles.stringValue
                        self.dribblesSuccessLabel.text = dribblesSuccess.stringValue
                        self.duelsLabel.text = duels.stringValue
                        self.duelsWonLabel.text = duelsWon.stringValue
                        self.playerImage.af.setImage(withURL: url! as URL)
                    }
                }
        })
        dataTask.resume()
    }

はい、完成で〜〜〜す! 画質悪っ笑
Videotogif.gif
後半のバテた感じが顕著ですが、ご愛嬌ということで!

それではみなさん、良いお年を!!!

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?