UIPickerVew によるメニュー選択 (1/3)不思議篇2012年11月10日 12:11

これでも、60秒タイマーとして動作する(左側)
不思議に思って、試作プロジェクトを作成してピッカーを組み込んでいろいろと実験してみた(写真右側)。プログラミングやデバッグの参考になれば幸いである。

  

タイマーの設定方法
分の数値 0がグレーにしてあるように、この位置で停止することは想定されていないし、普通に操作している限りまずはこのようにはならない。しかし、1 --> 0 方向にゆっくり戻しながら、素早くタップを繰り返し 0の位置でそっと指を離すと再現できる。最初は難しいが、慣れるとすぐにできるようになるから興味のある方は実際に試しててもらいたい (なお、逆方向 59 --> 0 に移動しながらはできない) 。

勝手にロジックを推測してみる
ドラムを回転して 0の位置で指を離した場合はつぎの行に強制的に移動させる。この辺は基本的にはだれが考えても同じのはず。

// 停止時のデリゲート
- (void) pickerView:(UIPickerView*)pickerView didSelectRow:(NSInteger)row
 inComponent:(NSInteger)component
{
    nowIndex_ = row;   
    // ドラムの表示 0の位置を index=0 と想定
    if (nowIndex_ == 0) {
        // 次の行に移動させる
        nowIndex_++;
        [picker_ selectRow:nowIndex_ inComponent:component animated:YES];
    }
}
これで、実際に試してみると意図した動作をすることがわかる。タイマーと同様にエンドレスのドラムを実現しないと逆方向は確かめられないないが、これだけでも解決すべき問題点の再現には十分だろう。

さらに推測をふくらます
この状態でタイマーをスタートしてから、キャンセルして戻ってくると 0 --> 1になっている。あるいはこの状態でアプリを終了してから再起動しても 0 --> 1に設定されている。多分タイマーを起動した時や、プログラムがバッググラウンドに遷移する際に呼ばれるデリゲードなどに、下記のようなコードが追加されているのだろう。

// 試作の場合は inComponent:0
[picker_ selectRow:nowIndex_ inComponent:1 animateed:NO]
これでも実用上は問題ないが問題点は未解決のままである。

(以下、 (2/3) 試行錯誤篇、(3/3)解決篇へ)