在button动作上传递参数:@selector

我想从我的dynamic生成的button传递电影url到MediaPlayer:

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

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

有没有其他解决scheme?

感谢帮助!

编辑。 find一个更好的方法!

button可以接收的一个参数是(id)sender 。 这意味着你可以创build一个新的button,从UIButtoninheritance,允许你存储其他预期的参数。 希望这两个片段说明要做什么。

  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 } 

这是我最初的build议。

有一种方法可以达到同样的效果,但不是很好。 假设你想添加一个参数到你的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调用它,只要它知道在哪里find它。

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

就像我说的那样,这不是很好,但对我来说,我还没有find任何人提出任何其他工作解决scheme。

我find解决scheme。 电话:

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

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

然后,从(id)发件人取回参数。

我根据上面的信息提出了一个解决scheme。 我只是设置titleLabel 。 文本传递给我想要传递的string,并设置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; 

这样,就不需要inheritance或类别,并且没有内存泄漏

添加隐藏标题标签到参数是最好的解决scheme。

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

之后,我在Frame上抓取,可以说,在电影文件中得到3秒的帧,并从帧中生成图像文件。

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

因为我必须通过电影Url来播放电影function,所以我必须将button.titleLabel.text分配给一个电影url。 和button事件函数,从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; } 

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

UIControl参考

你从哪里得到你的方法?

我看到你的select器有一个参数,这个参数将被运行时系统填充。 它会通过这个参数发回你的button。

你的方法应该是这样的:

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

您可以设置button的标签,并从发件人进行访问

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

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

请参阅该方法和UIButton的参考

想想,你可以用一个类来扩展UIButton来实现这个方法。

在某些情况下我有另一种解决scheme。

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

当button被点击时,我们可以检查UIButton的所有子视图。 通常只有2个UILabel在里面。

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

这只适用于文本参数。

要添加到Tristan的答案 ,除(id)sender之外,button还可以接收(id)event

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

例如,如果button位于UITableView中的某个单元格中,并且您想要查找所indexPath的button的indexPath (尽pipe我想这也可以通过sender元素find),这会非常有用。

tl; dr:使用块

对于Obj-C ,例如,有一个CocoaPod SHControlBlocks ,它的用法是:

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

对于Swift ,我喜欢使用UIControl [1]的pod Actions :

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

并不是说有人正在阅读一个3岁的线程。 ::蟋蟀::

[1]和UIViewUITextFieldUIGestureRecognizerUIBarButtonItemTimer (正式的NSTimer)和NotificationCenter (正式的NSNotificationCenter)。