LoginSignup
2
2

More than 5 years have passed since last update.

UIPickerView(ドラムロール)の値が?(クエスチョン)になってしまって泥沼だった話

Posted at

ドラムロールを作ってくれと言われたので……

早速作ったわけですが、苦戦しました。
なんでかって、

iOS の画像.jpg

この1、2、3と縦に並んでる部分があるじゃないですか。
これがなんと、全てハテナマークで表示されてしまうんです(この写真では直っています)

色んなところでドラムロールのコードは掲載されていますがどれも同じ現象に悩まされました。
原因を調べてもなぜか数えるほどしか出てこない。。。(しかも解決していない)

これは記録しておこうということで。

まず、最初に調べたコードです。
ドラムロールを作る際にほぼ最低限必要な項目です。

import UIKit

// UIPickerViewDastaSourceとUIPickerViewDelegateは継承しなければエラーが出ます(fixをクリックすれば直してくれますが)
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {


    @IBOutlet weak var pickerTextField: UITextField!
    var array:[String] = ["1", "2", "3"]

    var pickerView = UIPickerView()

    override func viewDidLoad() {
        super.viewDidLoad()

        // pickerViewの位置と大きさを指定
        pickerView.frame = CGRect(x: 0, 
                                  y: 0, 
                                  width: UIScreen.main.bounds.size.width, 
                                  height: pickerView.bounds.size.height)

        // データソースを設定(よくわからない)
        pickerView.dataSource = self

        // デリゲートを設定(これを書くのを怠るとドラムロールにハテナすら表示されません。空っぽです)
        pickerView.delegate = self

        // 初期に選択されているドラムロールの値(必ずしも必要ではない)
        pickerView.selectRow(0, inComponent: 0, animated: true)

        // ここでいうtextViewはドラムロールで選択した値が収納されるテキストボックスです(画像でいう、2と書かれた場所)
        self.textView.inputView = pickerView
    }

    // ドラムロールの数です。今回は一つなので1を返します
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    // ドラムロールに表示する値の数を返します
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return array.count
    }
    // ドラムロールに表示する値(文字列)をここで返します
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return array[row]
    }
    // ドラムロールにて選択した値をtextViewに設定します
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        textView.text = array[row]
    }

このコードはなぜか有名で、これに一味加えたくらいのソースコードはわんさか出てきました。
しかしどれを使ってもいくつか警告やエラーが出てきて、クリックして直してくとドラムロールの値はハテナとなりました。

ちなみにこれをfixをクリックして直していくと

    // ドラムロールに表示する値(文字列)をここで返します
    fileprivate func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return array[row]
    }

↑fileprivateがつけられてしまいます。

どうやらこれが原因だったようで。。。

多分、fileprivateがつけられてしまう理由は、pickerViewという関数が三つあって、内二つが引数の数と型が一致しているからかと思います。
関数の区別がつかないからとりあえずfileprivateを付けろ的なw
そのせいで外から呼び出せなかったのだと思います。
値が取れないのでブレイクポイントを張ったらそこを通らず、初めて気づきましたw

とりあえずfileprivateを外して引数の型など諸々をいじったところ、最終的には

    // ドラムロールに表示する値(文字列)をここで返します
    func pickerView(_ pickerView: UIPickerView, viewForRow row: Int,forComponent component: Int, reusing view: UIView?) -> UIView{
        let label = UILabel()
        label.text = array[row]
        label.textAlignment = NSTextAlignment.center
        return label
    }

これに書き換えたところうまく表示されました。
さっきまでStringで返してたのにUIViewで返して大丈夫?と心配だったのですが問題ありませんでした。

すごく初歩的なのでしょうけど、 pickerView自体ブラックボックスで仕組みがイメージできていないためこのような初歩的な部分に気づかなかったのだと思います。

精進しますw

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