FC2ブログ

--
--/--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2012
03/12


UIPickerView の項目の選択がうまく反映されない理由を紐解くヒントになるかもしれないエントリ。

UIPickerView にて各列の項目を選択したときにコールされる delegate メソッド
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
は、この UIPickerView の各コンポーネントが全て静止して始めてコールされる。

例えば、3つのコンポーネントを持つ UIPickerView の一番左のコンポーネントを選択(動か)している最中に他のコンポーネントを操作すると、左のコンポーネントが停止しても、他コンポーネントがスクロール中であれば、そのタイミングで上記メソッドはコールされない。
ということ。

どういうことかわかりやすくするためにあるサンプルを書いてみました。

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource> {

UILabel *selectValueLabel; // ピッカー選択変更時処理がコールされた際の値表示ラベル
NSInteger value1; // 左の列の選択値
NSInteger value2; // 中央の列の選択値
NSInteger value3; // 右の列の選択値
}

@end


画面は下のような感じです。

UIPickerViewSample.png

画面上部のラベルが selectValueLabel。
ピッカーに関してはコンポーネントの値を左からそれぞれ、value1、value2、value3と定義しています。
ピッカーの選択を変更したタイミングで、上記ラベルの値も書き換えるといった簡単なアプリです。

で、問題のある処理はこちら。
(すべての処理は書きませんが、上記メソッドの部分だけ書きます)

ViewController.m

#pragma mark ピッカー選択変更時処理
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

// 値が変更された列の、選択された行番号を変数に格納
switch (component) {
case 0:
value1 = row;
break;
case 1:
value2 = row;
break;
case 2:
value3 = row;
break;
default:
break;
}

// ラベルに表示
[selectValueLabel setText:[NSString stringWithFormat:@"%d %d %d", value1, value2, value3]];
}


このサンプルで問題なのは、コンポーネントを同時に動かしてしまうと、最後に停止したコンポーネントの値しか取得できないということ。
画面はこんな感じで表示されます。
左のコンポーネントを9までスクロールしている最中に、真ん中のコンポーネントを9までスクロールさせたパターンのキャプチャです。

UIPickerViewSampleError.png


結論としては、
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
メソッドがコールされるタイミングで、全てのコンポーネントの値を取得するべきである。

修正したサンプルはこれ。

ViewController.m (修正版)

#pragma mark ピッカー選択変更時処理
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

// 全ての列の選択行番号を変数に格納
value1 = [pickerView selectedRowInComponent:0];
value2 = [pickerView selectedRowInComponent:1];
value3 = [pickerView selectedRowInComponent:2];
// ラベルに表示
[selectValueLabel setText:[NSString stringWithFormat:@"%d %d %d", value1, value2, value3]];
}


コンポーネントが停止したタイミングで、全てのコンポーネントの現在選択中の値を取得してしまえば、上記の問題はなくなるはずです。

UIPickerViewSampleModified.png


僕の気のせいだと思いますが、iOS4.x のときにこんな問題なかったような。。。

プロフィール

Taku Sasahara

Author:Taku Sasahara
Hello world!!

バジルの息子。
法学部法律学科卒。
バリバリの文系プログラマです。
ペーペーです。

Facebook

My faborite books
僕のお気に入り書籍の本棚

最新トラックバック

スポンサーリンク

検索フォーム

ブロとも申請フォーム

QRコード
QR

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。