web-dev-qa-db-ja.com

ボタンaction:@selectorのパラメーターを渡す

動的に生成されたボタンからMediaPlayerに映画のURLを渡します。

_[button addTarget:self action:@selector(buttonPressed:) withObject:[speakers_mp4 objectAtIndex:[indexPath row]] forControlEvents:UIControlEventTouchUpInside];
_

しかし、action:@selector() withObject:は機能しませんか?

他の解決策はありますか?

手伝ってくれてありがとう!

50
Pascal Bayer

編集。きちんとした方法を見つけました!

ボタンが受け取ることができる引数の1つは(id)sender。これは、UIButtonを継承する新しいボタンを作成して、他の目的の引数を保存できることを意味します。うまくいけば、これらの2つのスニペットが何をすべきかを示しています。

  myOwnbutton.argOne = someValue
  [myOwnbutton addTarget:self action:@selector(buttonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];

そして

- (IBAction) buttonTouchUpInside:(id)sender {
  MyOwnButton *buttonClicked = (MyOwnButton *)sender; 
  //do as you please with buttonClicked.argOne
}

これは私の最初の提案でした。

同じ結果を達成する方法はありますが、見栄えはよくありません。 navigateメソッドにパラメーターを追加するとします。以下のコードでは、そのパラメーターをnavigateに渡すことはできません。

[button addTarget:self action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

これを回避するには、ナビゲートmethodを独自のクラスに移動し、そのクラスの属性として「パラメーター」を設定します...

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

もちろん、navigateメソッドを元のクラスに保持し、それがどこにあるかを知っている限り、navAidによって呼び出すことができます。

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.whereToCallNavigate = self
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

私が言ったように、それはきれいではありませんが、私にとってはうまくいきました。

61
WoodenKitty

私は解決策を見つけました。呼び出し:

-(void) someMethod{
    UIButton * but;
    but.tag = 1;//some id button that you choice 
    [but addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
}

そして、ここで呼び出されるメソッド:

-(void) buttonPressed : (id) sender{
    UIButton *clicked = (UIButton *) sender;
    NSLog(@"%d",clicked.tag);//Here you know which button has pressed
}
32
orafaelreis

上記の情報に一部基づいてソリューションを作成しました。 titleLabel .. text を渡す文字列に設定し、titleLabel.hidden = YESを設定するだけです。

このような :

    UIButton *imageclick = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
    imageclick.frame = photoframe;
    imageclick.titleLabel.text = [NSString stringWithFormat:@"%@.%@", ti.mediaImage, ti.mediaExtension];
    imageclick.titleLabel.hidden = YES;

このように、継承またはカテゴリの必要はなく、メモリリークもありません。

12
Trausti Thor

MyButtonという名前のUIButtonをサブクラス化し、MyButtonのプロパティによってパラメーターを渡すことができます。

次に、(id)senderからパラメーターを取得します。

11
AechoLiu

非表示のtitleLabelをパラメーターに追加するのが最適なソリューションです。

アセットブロックを列挙することにより、携帯電話のアルバムにmovファイルのNSURLを格納する配列arrUrlを生成しました。

その後、フレームを取得して、たとえば、ムービーファイルで3:00秒にフレームを取得し、フレームから画像ファイルを生成します。

次に、arrUrlをループし、プログラムを使用してボタン内に画像を含むボタンを生成し、self.viewのサブビューにボタンを追加します。

ムービーのURLをplayMovie関数に渡す必要があるため、button.titleLabel.textに1つのムービーURLを割り当てる必要があります。ボタンイベント関数は、buttontitleLable.txtからURLを取得します。

-(void)listVideos

{
   for(index=0;index<[self.arrUrl count];index++{
      UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
      imageButton.frame = CGRectMake(20,50+60*index,50,50);

      NSURL *dUrl = [self.arrUrl objectAtIndex:index];

      [imageButton setImage:[[UIImage allow] initWithCGImage:*[self getFrameFromeVideo:dUrl]] forState:UIControlStateNormal];
      [imageButton addTarget:self action:@selector(playMovie:) forControlEvents:UIControlEventTouchUpInside];
      imageButton.titleLabel.text = [NSString strinfWithFormat:@"%@",dUrl];
      imageButton.titleLabel.hidden = YES;

      [self.view addSubView:imageButton];
   }
}

-(void)playMovie:(id) sender{
   UIButton *btn = (UIButton *)sender;
   NSURL *movUrl = [NSURL URLWithString:btn.titleLabel.text];
   moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movUrl];
   [self presentMoviePlayerViewControllerAnimated:moviePlayer];
}

-(CGIImageRef *)getFrameFromVideo:(NSURL *)mUrl{
   AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mUrl option:nil];
   AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
   generator.appliesPreferredTrackTransform = YES;
   NSError *error =nil;
   CMTime = CMTimeMake(3,1);
   CGImageRef imageRef = [generator copyCGImageAtTime:time actualTime:nil error:&error];
   if(error !=nil) {
      NSLog(@"%@",sekf,error);
   }

   return @imageRef;
}
3
showmyroutes

tl; dr:ブロックを使用

たとえば、Obj-Cには、CocoaPod SHControlBlocks があり、その使用方法は次のとおりです。

[self.btnFirst SH_addControlEvents:UIControlEventTouchDown withBlock:^(UIControl *sender) {
    [weakSelf performSegueWithIdentifier:@"second" sender:nil];
    NSLog(@"first");
  }];

Swiftの場合、ポッド Actions が大好きです。これにより、UIControls [1]のブロックが許可されます。

// UIControl
let button = UIButton()
button.add(event: .touchUpInside) {
    print("Button tapped")
    playMusic(from: speakers_mp4, withSongAtPosition: indexPath.row)
}

誰もが3年前のスレッドを読んでいるわけではありません。 ::クリケット::

[1]およびUIViewUITextFieldUIGestureRecognizerUIBarButtonItemTimer(正式にはNSTimer)、およびNotificationCenter (正式にはNSNotificationCenter)。

1
AmitaiB

正しい方法は- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEventsであると思います

IControlリファレンス

メソッドはどこから入手しますか?

セレクタに引数があることがわかります。その引数はランタイムシステムによって入力されます。その引数を通じてボタンを送り返します。

メソッドは次のようになります。

- (void)buttonPressed:(id)BUTTON_HERE { }

1
vodkhang

ボタンのタグを設定し、アクションの送信者からアクセスできます

[btnHome addTarget:self action:@selector(btnMenuClicked:)     forControlEvents:UIControlEventTouchUpInside];
                    btnHome.userInteractionEnabled = YES;
                    btnHome.tag = 123;

呼び出された関数内

-(void)btnMenuClicked:(id)sender
{
[sender tag];

    if ([sender tag] == 123) {
        // Do Anything
    }
}
1
Fawad Masud

Tristan's answer に追加するために、ボタンは(id)event に加えて (id)sender

- (IBAction) buttonTouchUpInside:(id)sender forEvent:(id)event { .... }

これは、たとえば、ボタンが UITableView のセルにあり、 indexPath のタッチされたボタン(これはsender要素でも見つけることができると思いますが)。

0
newenglander

場合によっては別の解決策があります。

パラメータを非表示のUILabelに保存します。次に、このUILabelをUIButtonのサブビューとして追加します。

ボタンがクリックされると、UIButtonのすべてのサブビューをチェックできます。通常は2 UILabelのみです。

1つはUIButtonのタイトル、もう1つは追加したばかりのタイトルです。 UILabelのテキストプロパティを読み取ると、パラメーターが取得されます。

これは、テキストパラメータにのみ適用されます。

0
LetBulletFlies

UIButtonは、UIControlを継承するため、addTarget:action:forControlEvents:に応答します。ただし、addTarget:action:withObject:forControlEventsには応答しません。

メソッドのリファレンス および IButton を参照

UIButtonをカテゴリで拡張して、そのメソッドを実装することも考えられます。

0
Daniel