はじめに
どうも、プログラミング未経験で学習中のはるさんです。
今回はStoryboardで複数のUIPickerViewを実装するについて説明していきたいと思います。
一つの画面に複数のUIPickerViewを表示する際になかなか手こずってしまいました。
理解すれば簡単に実装できます。
記事の対象者
- Swift学習を初めたばかりの方
- UIPickerViewを複数設置でお困りの方
記事を執筆時点での筆者の環境
- Xcode 14.2
- Swift 5.5.2
- iOS 16.2
1.例題内容
1-1. 条件
- 画面に二つのUIPickerViewと二つのUILabelを配置
- UIPickerViewで選択した値をUILabelを表示させる
- 値は「動物」と「果物」とする
1-2. 全体のコード
この段階では「動物」の値しか表示させることができません。
animalPickerViewとfruitUIPickerViewの両方に同じ値が出力されます。
import UIKit
class ViewController: UIViewController {
//1個目、動物のUIPickerViewの選択内容を表示するUILabel
@IBOutlet weak var animalLabel: UILabel!
// 1個目、動物のUIPickerView
@IBOutlet weak var animalPickerView: UIPickerView!
// 2個目、フルーツのUILabel
@IBOutlet weak var fruitLabel: UILabel!
// 2個目、フルーツのUIPickerView
@IBOutlet weak var fruitUIPickerView: UIPickerView!
// 1個目、動物のUIPickerViewに表示する値の配列
var animalValue = ["犬", "猫", "兎", "狐"]
// 2個目、フルーツのUIPickerViewに表示する値の配列
var fruitValue = ["リンゴ", "オレンジ", "ブドウ", "バナナ"]
override func viewDidLoad() {
super.viewDidLoad()
// animalPickerViewとfruitUIPickerViewのdataSourceとdelegateをセット
animalPickerView.dataSource = self
animalPickerView.delegate = self
fruitUIPickerView.dataSource = self
fruitUIPickerView.delegate = self
}
}
// UIPickerViewに表示設定
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
// UIPickerViewの列の数
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// UIPickerViewの行数(要素の数)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return animalValue.count
}
// UIPickerViewに表示する配列(内容)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return animalValue[row]
}
// UIPickerViewが選択された時の挙動
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
animalLabel.text = animalValue[row]
}
}
1-3. シュミレーターで確認
2. if文で分岐処理する
2-1. 変更したコード
// UIPickerViewに表示設定
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
// UIPickerViewの列の数
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// UIPickerViewの行数(要素の数)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView === animalPickerView {
return animalValue.count
} else if pickerView === fruitPickerView {
return fruitValue.count
} else {
return animalValue.count
}
}
// UIPickerViewに表示する配列(内容)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView === animalPickerView {
return animalValue[row]
} else if pickerView === fruitPickerView {
return fruitValue[row]
} else {
return animalValue[row]
}
}
// UIPickerViewが選択された時の挙動
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView === animalPickerView {
animalLabel.text = animalValue[row]
} else if pickerView === fruitPickerView {
fruitLabel.text = fruitValue[row]
} else {
animalLabel.text = animalValue[row]
}
}
}
2-2. 解説
手法としてはデリゲートメソッド内にif文で処理を分岐させます。この時の対象を
オブジェクトであるanimalPickerView
とfruitUIPickerView
にします。
演算子を==
でも動きますが、オブジェクトを対象とする場合は参照比較演算子で
ある===
とすると安全です。
2-3. シュミレータで確認
2-4. 全体のコード
import UIKit
class ViewController: UIViewController {
//1個目、動物のUIPickerViewの選択内容を表示するUILabel
@IBOutlet weak var animalLabel: UILabel!
// 1個目、動物のUIPickerView
@IBOutlet weak var animalPickerView: UIPickerView!
// 2個目、フルーツのUILabel
@IBOutlet weak var fruitLabel: UILabel!
// 2個目、フルーツのUIPickerView
@IBOutlet weak var fruitPickerView: UIPickerView!
// 1個目、動物のUIPickerViewに表示する値の配列
var animalValue = ["犬", "猫", "兎", "狐"]
// 2個目、フルーツのUIPickerViewに表示する値の配列
var fruitValue = ["リンゴ", "オレンジ", "ブドウ", "バナナ"]
override func viewDidLoad() {
super.viewDidLoad()
// animalPickerViewとfruitUIPickerViewのdataSourceとdelegateをセット
animalPickerView.dataSource = self
animalPickerView.delegate = self
fruitPickerView.dataSource = self
fruitPickerView.delegate = self
}
}
// UIPickerViewに表示設定
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
// UIPickerViewの列の数
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// UIPickerViewの行数(要素の数)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView === animalPickerView {
return animalValue.count
} else if pickerView === fruitPickerView {
return fruitValue.count
} else {
return animalValue.count
}
}
// UIPickerViewに表示する配列(内容)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView === animalPickerView {
return animalValue[row]
} else if pickerView === fruitPickerView {
return fruitValue[row]
} else {
return animalValue[row]
}
}
// UIPickerViewが選択された時の挙動
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if pickerView === animalPickerView {
animalLabel.text = animalValue[row]
} else if pickerView === fruitPickerView {
fruitLabel.text = fruitValue[row]
} else {
animalLabel.text = animalValue[row]
}
}
}
3. tagでも判別できる
Storyboardの設定でtagという機能があります。
これを使って判別する方法もあります。
当初はこちらを使っていましたが、
TwitterでUIPickerView
のインスタンスで判別できることを教えていただきました。
どちらでも望んだ挙動は実現できますが、個人的にtagはおすすめしません。
デメリットとして実装までの行程が増える、コードとしての可読性が下がる点が挙げられます。
一応簡単にではありますが、tagを使った実装も載せておきます。
3-1. StoryboardでUIPickerViewにtagをつける
ここを設定しないとtagが反映されません。
3-2. viewDidLoad
内でtagを登録
override func viewDidLoad() {
super.viewDidLoad()
// animalPickerViewとfruitUIPickerViewのdataSourceとdelegateをセット
animalPickerView.dataSource = self
animalPickerView.delegate = self
fruitPickerView.dataSource = self
fruitPickerView.delegate = self
animalPickerView.tag = 1
fruitPickerView.tag = 1
}
}
3-2. デリゲートメソッドで処理を書く
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {
// UIPickerViewの列の数
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// UIPickerViewの行数(要素の数)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 1 {
return animalValue.count
} else if pickerView.tag == 2 {
return fruitValue.count
} else {
return animalValue.count
}
}
// 以下のメソッド内も同様に書き換える。省略
終わりに
いかがだったでしょうか?
複数のUIPickerViewが実装できれば、アプリ開発において
レイアウトの幅も広がります。
この記事が初学者の方々の学習において、少しでもお役にたてれば幸いです。
参考記事
[iPhone] UIPickerView の基本的な設定 | iOS アプリ開発
[Swift5]同じビュー内に違う値を持つPickerViewを2つ表示する方法 | えとログ