#はじめに
私がSwiftを勉強し始めて一番最初に苦戦したのがPickerViewでした。なので個人でのQiitaの最初の投稿もPickerViewについてです!
私だけでなく、よくわかんないって人が意外と多いと感じたので簡単にまとめてみました。
参考までにどうぞ。
#storyboardの作成
今回は複数の列を選択できるPickerViewを作成するので、わかりやすくするためにTextFieldはstoryboardで設置した。
#手順
①デリゲートメソッドを追加
②変数宣言
③PickerViewの設定
④toolbarの設定
#①デリゲートメソッドを追加
UIPickerViewDelegate, UIPickerViewDataSource
これらを追加します。
(最終的なコードは最後にまとめて表示します。)
#②変数宣言
@IBOutlet weak var year:UITextField!
@IBOutlet weak var month:UITextField!
@IBOutlet weak var day:UITextField!
var PickerView = UIPickerView()
storyboardに配置したTextFieldと今回使うPickerViewの宣言を行います。
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
}
またViewDidLoadの中に、この画面でPickerViewのデリゲートメソッドを使用することを言っておきます。
ここは忘れやすいので注意!
#③PickerViewの設置
さて準備も終わったところなのでいよいよ本題のPickerViewの設定です。
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の中身について具体的に設定していきます
####列の設定
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 3
}
まず列の個数を選択します。西暦、年、日の3つを同時に記入したいので、列の個数は3です。
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
}
}
それぞれのTextFieldで選択したい値の数が違うのでswich文を用いて条件分岐を行います。
デリゲートメソッドが記入されている状態で"numb"ぐらいまで打つと選択肢として出てきますよ!!
####表示名の設定
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に表示させます
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の実装は完了しました!
こんな感じになってれば完璧です。
次はtoolbarを実装してちょっとだけおしゃれにしていきましょう
###そもそもtoolbarって?
これから説明するコードを実装すると以下のようになります。
そうなんです。上にちょっぴり生えてきたものありますよね?それが今回表示させたいtoolbarです。
今から解説していきますね!
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が画面から消えるということにします!
簡略化してすいません🙇♂️
コードは以下の通りになります。
@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つの場合などはこのように分岐しなくて大丈夫です。
また、もう少し綺麗な書き方がある!とか少し違う!とかツッコミたくなるかもしれませんがご放念ください。