LoginSignup
4
3

More than 3 years have passed since last update.

【Swift】UIPickerViewについて コードで表示/複数列

Last updated at Posted at 2021-02-28

はじめに

私がSwiftを勉強し始めて一番最初に苦戦したのがPickerViewでした。なので個人でのQiitaの最初の投稿もPickerViewについてです!
私だけでなく、よくわかんないって人が意外と多いと感じたので簡単にまとめてみました。
参考までにどうぞ。

storyboardの作成

今回は複数の列を選択できるPickerViewを作成するので、わかりやすくするためにTextFieldはstoryboardで設置した。
スクリーンショット 2021-03-01 1.59.35.png

手順

①デリゲートメソッドを追加
②変数宣言
③PickerViewの設定
④toolbarの設定

①デリゲートメソッドを追加

UIPickerViewDelegate, UIPickerViewDataSource

これらを追加します。
(最終的なコードは最後にまとめて表示します。)

②変数宣言

ViewController.swift
    @IBOutlet weak var year:UITextField!
    @IBOutlet weak var month:UITextField!
    @IBOutlet weak var day:UITextField!
    var PickerView = UIPickerView()

storyboardに配置したTextFieldと今回使うPickerViewの宣言を行います。

ViewController.swift
    var yearArray:[String] = ["2021","2022","2023","2024","2025","2026","2027","2028","2029","2030"]
    var monthArray:[String] = ["1","2","3","4","5","6","7","8","9","10","11","12"]
    var dayArray:[String] = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"]

また今回表示させる配列も宣言しておきます。

ViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()
        PickerView.delegate = self
        PickerView.dataSource = self
}

またViewDidLoadの中に、この画面でPickerViewのデリゲートメソッドを使用することを言っておきます。
ここは忘れやすいので注意!

③PickerViewの設置

さて準備も終わったところなのでいよいよ本題のPickerViewの設定です。

ViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()
        //さっき書き込んだところ
        PickerView.delegate = self
        PickerView.dataSource = self
     //追記
        year.inputView = PickerView
        month.inputView = PickerView
        day.inputView = PickerView

}

まずViewDidLoadの中で、先ほど宣言したTextFieldにPickerViewを当てはめます。
これを行わないとtextFieldを選択してもPickerViewが下から出てきません。

ここからはPickerViewの中身について具体的に設定していきます

列の設定

ViewController.swift
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 3
    }

まず列の個数を選択します。西暦、年、日の3つを同時に記入したいので、列の個数は3です。
3を返すように設定しましょう。

行の設定

ViewController.swift
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch component {
        case 0:
            return yearArray.count
        case 1:
            return monthArray.count
        case 2:
            return dayArray.count
        default:
            return 0
        }
    }

それぞれのTextFieldで選択したい値の数が違うのでswich文を用いて条件分岐を行います。
デリゲートメソッドが記入されている状態で"numb"ぐらいまで打つと選択肢として出てきますよ!!

表示名の設定

ViewController.swift
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0:
            return yearArray[row]
        case 1:
            return monthArray[row]
        case 2:
            return dayArray[row]
        default:
            return "error"
        }
    }

表示名って何?って思う人もいるかもしれませんが、簡単にいうとPickerViewの内容を記入するものになります。
このコードがないとPickerViewの内容が"?"となって選択されているものがどれかわからないので、必ず書きましょう。

以上でPickerViewの設定は終了となります。

次はPickerViewで選択したものをTextFieldに表示させます

ViewController.swift
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        switch component {
        case 0:
            year.text = yearArray[row]
        case 1:
            month.text = monthArray[row]
        case 2:
            day.text = dayArray[row]
        default:
            break
        }
    }

簡単ですね。同じようにして表示させるだけです。

ここまででPickerViewの実装は完了しました!

こんな感じになってれば完璧です。
Simulator Screen Shot - iPhone 11 - 2021-03-01 at 03.01.46.png

次はtoolbarを実装してちょっとだけおしゃれにしていきましょう

そもそもtoolbarって?

これから説明するコードを実装すると以下のようになります。
Simulator Screen Shot - iPhone 11 - 2021-03-01 at 03.12.44.png

そうなんです。上にちょっぴり生えてきたものありますよね?それが今回表示させたいtoolbarです。

今から解説していきますね!

ViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()
        //さっき書き込んだところ
        PickerView.delegate = self
        PickerView.dataSource = self
     //さっき書き込んだところ
        year.inputView = PickerView
        month.inputView = PickerView
        day.inputView = PickerView
    //追記
     let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50))
        let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let done = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ViewController.donePressed))
        let cancel= UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ViewController.cancelPressed))
        toolbar.setItems([cancel , space, done ], animated: true)

        year.inputAccessoryView = toolbar
        month.inputAccessoryView = toolbar
        day.inputAccessoryView = toolbar

}

最初にtoolbarを作らないといけませんね。なのでViewDidLoadの中で上の追記のようにします。
まず、toolbarをどのようなものするかを決め、そしてそこに表示させるアイテム(ここではcancelとdoneとspace)を設定します。次ににtoolbarの中に順番に表示させて見やすいようになるまで工夫します。
そして最後に、toolbarを表示させるコードを書いたら完了です。

ここで気づいた方もいるかもしれませんが、
「"ViewController.donePressed" , "ViewController.cancelPressed"」 ってなんだよ!って思いませんでしたか?
ごめんなさい...順番が難しくて...今から解説していきます!

まず何かと簡単にいうと、cancelボタンとdoneボタンが押された時にどうするかというものですね!
それを決めないとtoolbarを置いた意味がありません。

今回はcancelボタンとdoneボタン両方ともPickerViewが画面から消えるということにします!
簡略化してすいません🙇‍♂️
コードは以下の通りになります。

ViewController.swift
    @objc func donePressed() {
           view.endEditing(true)
       }

    @objc func cancelPressed() {
           view.endEditing(true)
       }

これをclass内のViewDidLoadの外に記入してください。

はい!これで以上になります!

最終的には以下のようになります。

import UIKit

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

    @IBOutlet weak var year:UITextField!
    @IBOutlet weak var month:UITextField!
    @IBOutlet weak var day:UITextField!
    var PickerView = UIPickerView()

    var yearArray:[String] = ["2021","2022","2023","2024","2025","2026","2027","2028","2029","2030"]
    var monthArray:[String] = ["1","2","3","4","5","6","7","8","9","10","11","12"]
    var dayArray:[String] = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"]

    override func viewDidLoad() {
        super.viewDidLoad()

        PickerView.delegate = self
        PickerView.dataSource = self

        year.inputView = PickerView
        month.inputView = PickerView
        day.inputView = PickerView

        let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height:50))
        let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
        let done = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(ViewController.donePressed))
        let cancel = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ViewController.cancelPressed))
        toolbar.setItems([cancel , space, done ], animated: true)

        year.inputAccessoryView = toolbar
        month.inputAccessoryView = toolbar
        day.inputAccessoryView = toolbar

    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 3
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch component {
        case 0:
            return yearArray.count
        case 1:
            return monthArray.count
        case 2:
            return dayArray.count
        default:
            return 0
        }
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0:
            return yearArray[row]
        case 1:
            return monthArray[row]
        case 2:
            return dayArray[row]
        default:
            return "error"
        }
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        switch component {
        case 0:
            year.text = yearArray[row]
        case 1:
            month.text = monthArray[row]
        case 2:
            day.text = dayArray[row]
        default:
            break
        }
    }


    @objc func donePressed() {
           view.endEditing(true)
       }

    @objc func cancelPressed() {
           view.endEditing(true)
       }

}

さいごに

今回はswich文を用いて条件分岐しましたが、列が1つの場合などはこのように分岐しなくて大丈夫です。
また、もう少し綺麗な書き方がある!とか少し違う!とかツッコミたくなるかもしれませんがご放念ください。

4
3
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
4
3