senderについて | 渋谷で働くUnity野郎

渋谷で働くUnity野郎

備忘録として有効活用していきます。

UIButtonを使っていたときの話。

-----------------------------

//ボタンのインスタンス作成
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeRoundRect] retain];

//ボタンに表示される文字列を書き込む
[btn setTitle:@"xxxxx" forState:UIControlStateNormal];
(※forState:の引数には、以下の3つがある。
 UIControlStateNormal 通常の状態
UIControllStateHighlighted ハイライトの状態
UIControlStateDisabled 無効の状態)

//ボタンのフレームを作成
[btn setFrame:CGRectMake(x, y, tx, ty)];

これに関しては以下のようにするとサイズの作成が楽になる。
//文字列のサイズにボタンを合わせる
[btn sizeToFit];
//フレーム作成
[btn setFrame:CGRectMake(0, 0, btn.frame.size.width, btn.frame.size.height)];
//ボタンが押された時の処理
[btn addTarget:self
action:@selector(使用するメソッド)
forControlEvents:UIControlEventTouchDown];

-----------------------------

この時の@selectorが曲者だった。
指定したメソッドに、押されたボタン自体を引数として持って行きたい時どうすればいいか?
私は普通にボタンを引数として持って行けばよいのでは?、と考えたが駄目だった。

- (void) didPushBtn (UIButton *) pushedButton;


これがなぜ駄目なのかはselector自身の仕様のためである。
(詳細に関しては難しいので割愛する)

解決策:
UIControl (UIButtonは、UIControlのサブクラス)のアクションに使えるメソッドの形式は以下の3パターンに決まっている。

(1) - (void) didPushBtn
→ 引数なし
(2) - (void) didPushBtn:(id)sender
→ アクションを送ったコントロール(ここではボタン)を引数に持つ
(3)- (void) didPushBtn:(id)sender forEvent:(UIEvent *event)
→タッチなどのイベント情報も引数に与える


まさか仕様ですでに決まっていたとはなぁ・・・、とガックシ。

ちなみに
@selector(メソッド名:) で引数1個の処理
@selector(メソッド名:引数名:)で引数2個の処理
となる。

ちなみに引数として持っていったボタンをどう区別するか?に関して疑問に思うだろう。
それに関して、以上のことを踏まえて再度書き直すと以下のようにすればよい。

-----------------------------

//ボタンのインスタンス作成
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeRoundRect] retain];

//ボタンに表示される文字列を書き込む
[btn setTitle:@"xxxxx" forState:UIControlStateNormal];

//ボタンのフレームを作成
[btn setFrame:CGRectMake(x, y, tx, ty)];

これに関しては以下のようにするとサイズの作成が楽になる。
//文字列のサイズにボタンを合わせる
[btn sizeToFit];
//フレーム作成
[btn setFrame:CGRectMake(0, 0, btn.frame.size.width, btn.frame.size.height)];

//整数値を付け加える。この整数値によって、どのボタンであるかを区別すればよい。
btn.tag = 0;


//ボタンが押された時の処理
[btn addTarget:self
action:@selector(didPushBtn:)
forControlEvents:UIControlEventTouchDown];

- (void)didPushBtn:(id)sender{
//id型からUIButton型にキャストする
UIButton *pushedBtn = (UIButton *)sender;
if(pushedBtn.tag == 0){
NSLog(@"引数のボタンの名前はbtnでした。");
}else if(pusehdBtn.tag == 1){
~~~~~~~~~
}
}
-----------------------------

以上。