我想将动态生成的按钮中的电影网址传递给MediaPlayer:
[button addTarget:self action:@selector(buttonPressed:) withObject:[speakers_mp4 objectAtIndex:[indexPath row]] forControlEvents:UIControlEventTouchUpInside];
但action:@selector() withObject:
不起作用?
还有其他解决方案吗?
感谢您的帮助!
答案 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)
我部分地根据上述信息制定了解决方案。 我只是将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;
这样,就不需要继承或类别,也没有内存泄漏
答案 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
你从哪里获得你的方法?
我看到你的选择器有一个参数,该参数将由运行时系统填充。它将通过该参数向您发回按钮。
您的方法应如下所示:
- (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)
对于 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] UIView
,UITextField
,UIGestureRecognizer
,UIBarButtonItem
,Timer
(正式为NSTimer)和NotificationCenter
(正式为NSNotificationCenter) )。
答案 8 :(得分:0)
UIButton响应addTarget:action:forControlEvents:因为它继承自UIControl。但它不响应addTarget:action:withObject:forControlEvents:
请参阅reference for the method和UIButton
您可以使用类别扩展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
元素找到。