在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]和UIView , UITextField , UIGestureRecognizer , UIBarButtonItem , Timer (正式的NSTimer)和NotificationCenter (正式的NSNotificationCenter)。