📱

[iOS UIKit] UIPickerView入門

5 min read

はじめに

この記事ではiOSアプリ開発におけるUIPickerViewに好きなデータを表示する方法について紹介します。

後編もあるので良ければそちらもご覧ください↓
https://zenn.dev/fummicc1/articles/e3ed945c6d4dfc

完成

全体の流れ

flowchart TD
   subgraph Storyboard編
   Storyboard上にUI部品を配置する   
   end
   subgraph ViewController編   
   A[UIパーツの宣言] --> B[UIPickerViewDataSourceとUIPickerViewDelegateに準拠する]
   B --> C[ピッカーに表示するデータを保存する変数を宣言]
   C --> D[UIPickerViewDataSourceの実装]
   D --> E[UIPickerViewDelegateの実装]
   end

手順

StoryboardにUI部品を配置

最初にMain.storyboardから以下のように画面レイアウトを構築します。

使用したUIパーツ 個数
UIPickerView 2つ
UILabel 2つ

ViewController.swift

UIパーツの宣言

次に、ViewController.swiftにプログラムを書いていきます。
最初に先ほど作成したUIパーツを@IBOutlet varを用いて変数として宣言しておきます。

// ViewControllerクラスの中に記述
@IBOutlet var foodPickerView: UIPickerView! // 食べ物のPickerView
@IBOutlet var drinkPickerView: UIPickerView! // 飲み物のPickerView

UIPickerViewDataSourceとUIPickerViewDelegateの設定

UIPickerViewDataSourceを利用することで、PickerViewに表示されるデータを設定することができます。
UIPickerViewDelegateも後ほど利用します。UIPickerViewDelegateはPickerの見た目を変更したり、Pickerを選択した際の処理を記述する際に必要になります。

// viewDidLoadメソッドの中に記述
override func viewDidLoad() {
    super.viewDidLoad()
    
    // データソースの設定
    drinkPickerView.dataSource = self
    foodPickerView.dataSource = self
    
    // デリゲートの設定
    drinkPickerView.delegate = self
    foodPickerView.delegate = self
}

また、デリゲート/データソースにselfを代入する場合、以下のようなエラーが発生するはずです。

これは、ViewControllerUIPickerViewDelegateUIPickerViewDataSourceに準拠していないために発生するので、以下のようにViewControllerの頭を変更します。
また、AというクラスがBというデリゲートに準拠するには以下のように記述します。

class A: B { 
}
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

上に沿ってUIPickerViewDataSourceUIPickerViewDelegateを追記するとエラーが解消されます。

PickerViewに表示するデータの変数を宣言

次に、PickerViewに表示するデータを保存した変数を宣言します。
foodPickerViewに表示するデータはfoodArrayに保存し、drinkPickerViewに表示するデータはdrinkArrayに保存しています。

    // 飲み物のデータの配列
    var drinkArray: [String] = [
        "爽健美茶",
        "麦茶",
        "コーラ",
        "オレンジジュース",
        "天然水"
    ]
    
    // 食べ物のデータの配列
    var foodArray: [String] = [
        "ラーメン",
        "トマト",
        "生ハム",
        "きゅうり",
        "納豆",
        "お米"
    ]

データソースを実装

UIPickerViewDataSourceで定義されているメソッドは必ず実装する必要があり、2つのメソッドを実装していきます。

1. PickerViewの列の数を決めるメソッド

以下のメソッドになります。

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int

今回のアプリでは列は1つの想定なのでreturn 1としておきます。

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return 1
}
2. PickerViewの列一つに対する行の数を決めるメソッド
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int

今回はfoodPickerViewに対してはfoodArray.countだけ、drinkPickerViewに対してはdrinkArray.countの数だけを表示したいので以下のように書き換えます。

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    
    if pickerView == foodPickerView {
        return foodArray.count
    }
    
    if pickerView == drinkPickerView {
        return drinkArray.count
    }
    
    return 0
}

ここまでで実行をすると下のように、表示したい要素の数は一致しているのですが、中身に?と表示されてしまいます。

デリゲートの実装

?がピッカーに表示されてしまう現象はPickerViewに表示する文字列を設定していないために起こります。

UIPickerViewDelegateに準拠していれば、以下のメソッドが使用でき、ピッカーに表示されるタイトルを設定することができます。

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?

rowという引数には行数が格納されているので、foodArray[row]もしくはdrinkArray[row]として順にデータを設定していきます。ピッカーの行数を設定したときと同じく、pickerViewという引数がfoodPickerViewなのかdrinkPickerViewなのかで表示する文字列が変わってくるのでif文を用いて条件分岐しています。

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    if pickerView == foodPickerView {
        return foodArray[row]
    }
    if pickerView == drinkPickerView {
        return drinkArray[row]
    }
    return nil
}

完成(再掲)

コード全貌

GitHubにアップロードしました!

Discussion

ログインするとコメントできます