在按钮操作上传递参数:@selector

时间:2010-09-15 10:10:28

标签: iphone parameters action selector media-player

我想将动态生成的按钮中的电影网址传递给MediaPlayer:

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

action:@selector() withObject:不起作用?

还有其他解决方案吗?

感谢您的帮助!

11 个答案:

答案 0 :(得分:61)

修改。找到一个更简洁的方式!

按钮可以接收的一个参数是(id)sender。这意味着您可以创建一个继承自UIButton的新按钮,该按钮允许您存储其他预期参数。希望这两个片段说明了该做什么。

  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];

当然,您可以将导航方法保留在原始类中,并让navAid调用它,只要它知道在哪里找到它。

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

就像我说的那样,它不漂亮,但它对我有用,我没有找到任何人建议任何其他工作解决方案。

答案 1 :(得分:32)

我找到了解决方案。电话:

-(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
}

答案 2 :(得分:12)

我部分地根据上述信息制定了解决方案。 我只是将titleLabeltext设置为我要传递的字符串,并设置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;

这样,就不需要继承或类别,也没有内存泄漏

答案 3 :(得分:11)

您可以对名为MyButton的UIButton进行子类化,并通过MyButton的属性传递参数。

然后,从(id)发送者返回参数。

答案 4 :(得分:3)

将隐藏的titleLabel添加到参数是最佳解决方案。

我生成了一个数组arrUrl,它通过枚举资产块将mov文件的NSURL存储在我的手机相册中。

之后,我抓住Frame,让我们说,在电影文件中的3:00秒获取帧,并从帧中生成图像文件。

接下来,循环遍历arrUrl,并使用程序生成按钮中带有图像的按钮,将按钮附加到self.view的子视图。

因为我必须将电影Url传递给playMovie函数,所以我必须将button.titleLabel.text与一个电影网址分配。和按钮事件功能,从buttontitleLable.txt中检索网址。

-(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;
}

答案 5 :(得分:1)

我认为正确的方法应该是: - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

UIControl Reference

你从哪里获得你的方法?

我看到你的选择器有一个参数,该参数将由运行时系统填充。它将通过该参数向您发回按钮。

您的方法应如下所示:

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

答案 6 :(得分:1)

您可以设置按钮的标记并从发件人的操作中访问

[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
    }
}

答案 7 :(得分:1)

tl; dr:使用块

对于 Obj-C ,例如,有一个CocoaPod SHControlBlocks,其用法为:

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

对于 Swift ,我喜欢pod Actions,它允许UIControl s [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) )。

答案 8 :(得分:0)

UIButton响应addTarget:action:forControlEvents:因为它继承自UIControl。但它不响应addTarget:action:withObject:forControlEvents:

请参阅reference for the methodUIButton

您可以使用类别扩展UIButton以实现该方法。

答案 9 :(得分:0)

在某些情况下,我有另一种解决方案。

将您的参数存储在隐藏的UILabel中。然后将此UILabel添加为UIButton的子视图。

单击按钮时,我们可以检查UIButton的所有子视图。通常只有2个UILabel。

一个是UIButton的标题,另一个是你刚刚添加的标题。读取UILabel的文本属性,您将获得参数。

这仅适用于文本参数。

答案 10 :(得分:0)

要添加到Tristan's answer,除了(id)event之外,该按钮还可以接收(id)sender

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

例如,如果按钮位于UITableView的单元格中,并且您想要找到被触摸的按钮的indexPath,则此功能非常有用(尽管我认为这也可以是通过sender元素找到。