2
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.

【Swift】複数のUIPickerViewを実装する

Posted at

はじめに

どうも、プログラミング未経験で学習中のはるさんです。
今回はStoryboardで複数のUIPickerViewを実装するについて説明していきたいと思います。

一つの画面に複数のUIPickerViewを表示する際になかなか手こずってしまいました。

理解すれば簡単に実装できます。

記事の対象者

  • Swift学習を初めたばかりの方
  • UIPickerViewを複数設置でお困りの方

記事を執筆時点での筆者の環境

  • Xcode 14.2
  • Swift 5.5.2
  • iOS 16.2

1.例題内容

1-1. 条件

  1. 画面に二つのUIPickerViewと二つのUILabelを配置
  2. UIPickerViewで選択した値をUILabelを表示させる
  3. 値は「動物」と「果物」とする

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. シュミレーターで確認

前提のシュミレーター.gif

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文で処理を分岐させます。この時の対象を
オブジェクトであるanimalPickerViewfruitUIPickerViewにします。
演算子を==でも動きますが、オブジェクトを対象とする場合は参照比較演算子で
ある===とすると安全です。

2-3. シュミレータで確認

if文で分岐シュミレーター.gif

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が反映されません。

タグづけ1.png

タグづけ2.png

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つ表示する方法 | えとログ

2
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
2
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?