2011年2月15日火曜日

UIPickerView をコードで追加するのと、delegate と dataSource を外だしにしてみた

需要があるかどうかは知らないけど、今の機能に手軽にピッカーを追加できるように考えたら、ピッカーの追加とデータ取得だけを現在のコントローラに書いて、Delegate と dataSource はひとまとめにした別のファイルにしたらいいんじゃないかと思ってやってみた。いつものとおり、IBは使わないコース。まぁ練習。

// MyPicker.h
#import 
@interface MyPicker : NSObject <UIPickerViewDelegate,UIPickerViewDataSource>
{
  NSArray *      pickerData;
}
@property (nonatomic,retain) NSArray *      pickerData;
- (id) makeObj;
@end

// MyPicker.m
#import "MyPicker.h"
@implementation MyPicker
@synthesize pickerData;
-(id)makeObj
{
  NSArray * array = [[NSArray alloc] initWithObjects:@"test",@"test2",@"test3",nil];
  self.pickerData = array;
  [array release];
  return self;
}
#pragma mark -
#pragma mark UIPicker Data Source methods
  // コンポーネントの数を返す
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
  return 1;
}
  // コンポーネント毎(0始まり)の行数を返す
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
  return [pickerData count];
}
#pragma mark -
#pragma mark UIPicker delegate methods
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
  return [pickerData objectAtIndex:row];
}
#pragma mark -
- (void)dealloc {
  [pickerData release];
  [super dealloc];
}
@end

これで、現在のコントローラ中で以下のようにする。

// 現在のコントローラ.m

#import "MyPicker.h"

なんかの処理 {
  [self showPicker];
}
- (void)showPicker {
    // ピッカーを作って配置
  MyPicker * myPickObj = [[MyPicker alloc]autorelease]; // デリゲートとデータソースのオブジェクト
  [myPickObj makeObj];  // データいれる
    // ピッカーを描画
  UIPickerView * myPickerView = [[[UIPickerView alloc] init]autorelease];
  myPickerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  myPickerView.showsSelectionIndicator = YES;
  myPickerView.delegate = myPickObj; // ここを self 以外にするにはどうすればいいのか悩んでた
  myPickerView.dataSource = myPickObj; // 単にオブジェクト作って与えるだけで問題なかった
  [myPickerView setTag:123]; // 先日 #hidev で教わった、addSubview したビューを後で拾うためのタグ付け
  [self.view addSubview:myPickerView];

    // ボタンを作って配置
  UIButton* button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  button1.frame = CGRectMake(0,300,200,50);
  [button1 setTitle:@"Pickeeeeer" forState:UIControlStateNormal];
  [button1 addTarget:self action:@selector(showPickerSelected:) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:button1];
}

-(void)showPickerSelected:(id)sender{
    // タグでビューからピッカーを引っ張る
  UIPickerView * myPickerView = (UIPickerView *)[self.view viewWithTag:123];
  NSInteger row = [myPickerView selectedRowInComponent:0];
  NSString * message = [[NSString alloc] initWithFormat:@"row : %d",row];
  
  UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"選択したもの"
                                                  message:message
                                                 delegate:self
                                        cancelButtonTitle:@"OK"
                                        otherButtonTitles:nil];
  [alert show];
  [alert release];
  [message release];
}

使いどころもよくわからないまま書いたので、これの出番が本当にあるのかどうかはわからないけど、UIPickerViewの実装雛形としては使える、はず。MyPickerにデリゲートとデータソースを追いやることで、既存のソースとごっちゃにならないでいいかな、とか。

ちょっとぐぐっただけだと、デリゲートとデータソースを持ったViewControllerを使うサンプルばかりで、どうやってデリゲートとデータソースを外部化すればいいのか全然わからなかったけど、先日書いたサブクラス化のイメージでオブジェクト化すればいいんじゃね?と思ったらうまくいったのでよかった。

実はもっとうまい方法あるんだよ、とかあったら教えてください。

言うまでもないけど、先日書いた記事のとおり、Build and Analyzeしてるので、たぶん問題ないと思うんだけど、コードの書きっぷりとか、思う所があればそれも。。。

1 件のコメント:

  1. なんかちょっと使った後で再処理すると突然落ちる病を発症してる気がする。。。

    返信削除