Passing parameters to the button action: @selector

I want to pass the URL of the movie from my dynamically generated button to MediaPlayer:

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

but action:@selector() withObject: doesn't work?

Is there any other solution?

Thanks for the help!

+46
parameters iphone selector media-player action
Sep 15 '10 at 10:10
source share
11 answers

Change Found a more accurate way!

One argument a button can get is (id)sender . This means that you can create a new button that inherits from UIButton, which allows you to store other alleged arguments. Hopefully these two snippets illustrate what to do.

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

and

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



That was my initial suggestion.

There is a way to achieve the same result, but it is not very. Suppose you want to add a parameter to your navigate method. The code below will not allow you to pass this parameter to navigate .

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

To get around this, you can move the navigation method to your own class and set the "parameters" as attributes of this class ...

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

Of course, you can save the navigation method in the source class and call it navAid if it knows where to find it.

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

As I said, this is ugly, but it worked for me, and I did not find anyone offering any other working solution.

+59
Feb 08 '11 at 6:08
source share

I have found a solution. Call:

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

And here is the method:

 -(void) buttonPressed : (id) sender{ UIButton *clicked = (UIButton *) sender; NSLog(@"%d",clicked.tag);//Here you know which button has pressed } 
+30
Jun 09 2018-11-11T00:
source share

You can subclass a UIButton named MyButton and pass a parameter using the MyButton properties.

Then return the parameter from the sender (id).

+11
Sep 15 '10 at 14:20
source share

I made a decision, based in part on the information above. I just set titleLabel . text to the string I want to pass and set the title Label.hidden = YES

Like this:

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

Thus, there is no need for inheritance or category, and there is no memory leak.

+11
Nov 11 '11 at 9:44
source share

Adding a hidden Label header to a parameter is the best solution.

I generated an arrUrl array that stores the NSURL mov files in my phone album, listing the asset block.

After that, I grab onto the frame, say, I get the frame at 3:00 seconds in the movie file and generated an image file from the frame.

Next, loop over arrUrl, and use the program, generate the button with the image in the button, add the button in subview for self.view.

Since I need to pass an Url movie for the playMovie function, I need to assign button.titleLabel.text with one movie URL. and the button event function, extract the URL from the buttontitleLable.txt file.

 -(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
Dec 30 '15 at 23:19
source share

I think the correct method should be: - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

Link UIControl

Where do you get your method from?

I see that your selector has an argument, this argument will be populated by the runtime system. It will return you a button through this argument.

Your method should look like this:

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

+1
Sep 15 '10 at 10:18
source share

You can set the button tag and access it from the sender in action

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

In the called function

 -(void)btnMenuClicked:(id)sender { [sender tag]; if ([sender tag] == 123) { // Do Anything } } 
+1
Sep 12 '14 at 16:32
source share

The UIButton responds to addTarget: action: forControlEvents: as it inherits from UIControl. But it does not respond to addTarget: action: withObject: forControlEvents:

see link for method and UIButton

You can extend UIButton with a category to implement this method, I thought.

0
Sep 15 '10 at 10:38
source share

I have a different solution in some cases.

save your parameter in a hidden UILabel. then add this UILabel as a subpoint of UIButton.

when the button is pressed, we can check the UIButton for all sub-items. usually only 2 UILabel.

one is the UIButton header, the other is the one you just added. read this property of the UILabel text, you will get a parameter.

This applies only to the text parameter.

0
Jul 31 '11 at 3:19
source share

To add to Tristan's answer , the button can also accept a (id)event in addition to a (id)sender :

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

This can be useful if, for example, the button is in a cell in a UITableView and you want to find the indexPath button that was affected (although, I suppose, this can also be found through the sender element).

0
Dec 20
source share

tl; dr: Use blocks

For Obj-C , for example, CocoaPod SHControlBlocks , the use of which will be:

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

For Swift, I like the pod Actions , which allows blocks for UIControl [1]:

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

Not that anyone was reading a 3 year old thread. :: crickets ::

[1] And UIView , UITextField , UIGestureRecognizer , UIBarButtonItem , Timer (formally NSTimer) and NotificationCenter (formally NSNotificationCenter).

0
Mar 03 '17 at 15:06
source share



All Articles