How do we pass the arguments in #selector method for UIButton?
-(void)loadView{
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
btn1.tag=1;
[btn1 addTarget:self action:#selector(showRestaurant:tag:) forControlEvents:UIControlEventTouchDown];
btn1.frame = CGRectMake(2370.828125,1020.015625,35,34);
[imageView addSubview:btn1];
}
-(void)showRestaurant:(NSInteger)tag{
NSLog(#"x=%d",tag);
}
Here i want to get the tag value for this method showRestaurant.
Kindly help me regarding on this!
You should use
#selector(showRestaurant:)
and
-(void)showRestaurant:(UIButton*)btn
{
NSLog(#"tag=%d",btn.tag);
}
the selector should match the method signature, minus the "internal names" of the variables in the method.
Related
I have a method with multiple variables:
-(void) showImg:(UIBarButtonItem *)sender string1:(NSString *) string2:(NSString *);
I want to send NSString values (As this function is used for multiple elements).
This is how I add my action when no parameters are needed:
[myButton addTarget:self action:#selector(showImg) forControlEvents: UIControlEventTouchUpInside];
I tried adding parameters within the #selector like this:
[myButton performSelector #selector(showImg:string1:string2::) withObject:#"-1" withObject:#"-1"];
But this does not work. How may I call my function with multiple parameters directly inside the #selector?
You can make your UIButton call a function in between (like a middle man), to control the next functions parameters.
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
-(void) buttonTapped:(id)sender{
if(<some logical condition>){
[self showImg:sender string1:#"-1" string2:#"-1"];
}else {
[self showImg:sender string1:#"otherVal1" string2:#"otherVal2"];
}
}
-(void) showImg:(id)sender string1:(NSString *)string1 string2:(NSString*)string2 {
//Other logic
}
The following line is wrong :
[myButton performSelector #selector(showImg:string1:string2::) withObject:#"-1" withObject:#"-1"];
You can't pass parameters like this to the selector, that's why you have an error. I don't think you can pass multiple parameters to a selector. Maybe you can try to set a tag to your button with your const value (works with integers)
For example :
//Init your button......
[myButton setTag:1];
[myButton addTarget:self action:#selector(showImg:) forControlEvents: UIControlEventTouchUpInside];
- (void)showImg:(id)sender {
UIButton *btn = (UIButton *)sender;
int value = btn.tag;
}
Just a suggestion.. :)
I have the following in my viewdidload:
//Start/Pause Button
UIButton *buttonStart = [UIButton buttonWithType: UIButtonTypeCustom];
buttonStart.frame = CGRectMake(10,100,100,45);
[buttonStart setBackgroundImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[buttonStart addTarget:self action:#selector(pausePlayButtonTouched) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: buttonStart];
my selector method:
[self.buttonStart setBackgroundImage:[UIImage imageNamed:#"start.png"] forState:UIControlStateNormal];
NSLog(#"%#", self.buttonStart);
null is being logged to the console. And needless to say, the image for the button is not being changed.
What is wrong with my thinking?
btw buttonStart is being synthesized and has its own property (retain).
You are using both, an instance variable self.buttonStart accessed via property and a local variable buttonStart. Remove the declaration of that button from your implementation file and change the first line towards this:
self.buttonStart = [UIButton buttonWithType: UIButtonTypeCustom];
No need of property for buttonStart.Add target like this:
[buttonStart addTarget:self action:#selector(pausePlayButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
Now your selected method would be:
-(void)pausePlayButtonTouched:(id)sender
{
UIButton *btnPaused = sender;
NSLog(#"%#", btnPaused);
[btnPaused setBackgroundImage:[UIImage imageNamed:#"start.png"] forState:UIControlStateNormal];
}
Are you assigning self.buttonStart anywhere? Did you mean
self.buttonStart = [UIButton buttonWithType: UIButtonTypeCustom];
instead of
UIButton *buttonStart = [UIButton buttonWithType: UIButtonTypeCustom];
You should drop the '.png' tag from your filename, i.e. "pause", not "pause.png".
As far as I can see the assignment of buttonStart is missing.
Did you set self.buttonStart = buttonStart; ?
declaring UIButton *buttonStart = ... will shadow (in your local context) any created member that was created by #property (nonatomic, reatin) UIButton *buttonStart; (if you use LLVM 4.0+ your property declaration will create "UIButton *_buttonStart" as a member)
I want to programmatically add multiple UIButtons to a view - the number of buttons is unknown at compile time.
I can make one or more UIButton's like so (in a loop, but shorted for simplicity):
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(buttonClicked:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Button x" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 100.0, 120.0, 50.0);
[view addSubview:button];
Copied/Edited from this link:
How do I create a basic UIButton programmatically?
But how do I determine in buttonClicked: which button was clicked? I'd like to pass tag data if possible to identify the button.
You could either keep a reference to the actual button object somewhere that mattered (like an array) or set the button's tag to something useful (like an offset in some other data array). For example (using the tag, since this is generally must useful):
for( int i = 0; i < 5; i++ ) {
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:i];
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[aView addSubview:aButton];
}
// then ...
- (void)buttonClicked:(UIButton*)button
{
NSLog(#"Button %ld clicked.", (long int)[button tag]);
}
You can assign a tag to the button.
button.tag = i;
Then in -buttonClicked:, check the tag of the sender:
-(void)buttonClicked:(UIButton*)sender {
int tag = sender.tag;
...
}
I think this would be the best answer:-
http://conecode.com/news/2012/05/ios-how-to-create-a-grid-of-uibuttons/
For that give different tag to each button & use code like this:
[btn1 addTarget:self action:#selector(pressbtn:) forControlEvents:UIControlEventTouchUpInside];
[btn2 addTarget:self action:#selector(pressbtn:) forControlEvents:UIControlEventTouchUpInside];
& in method
-(void)pressbtn:(id)sender {
UIButton *button=sender;
if (button.tag==1)
{
NSLog(#"Press button 1");
}
if (button.tag==2)
{
NSLog(#"Press button 2");
}
and so on to check which button is called
If you want to add buttons at run time then there will be 10 20 50 or more than that. Then you should to use ui scroll view in this condition.
When the buttons will be generate then your scroll view size should be increased accordingly.
And you can write the code like this
scrollview = [[UIScrollView alloc] init];
scrollview.contentSize = CGSizeMake(INVOICE_ADDITEM_SCROLLVIEW_CONTENT_WIDTH, INVOICE_ADDITEM_SCROLLVIEW_CONTENT_HEIGHT);
scrollview.frame = CGRectMake(0,50, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
// scrollview.backgroundColor = [UIColor whiteColor];
scrollview.scrollsToTop = NO;
scrollview.delegate = self;
[self.view addSubview:scrollview];
for (int pos = 0; pos < 2; pos++) {
UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];
[but setImage:[UIImage imageNamed:#"checkbox.png"] forState:UIControlStateNormal];
[but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateSelected];
[but setFrame:CGRectMake(TXT_FLD_X_CORD+90, 295, 20, 20)];
// [but setCenter:CGPointMake( 50, i*40+20 )];
but.tag = pos;
/*if(pos==0)
{
[but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateNormal];
// [but setImage:[UIImage imageNamed:#"checkbox_active.png"] forState:UIControlStateSelected];
}*/
[but setCenter:CGPointMake(pos*90+125 ,310)];
[but addTarget:self action:#selector(checkboxButton:) forControlEvents:UIControlEventTouchUpInside];
[scrollview addSubview:but];
}
UIButton has a tag property. Use that and in your buttonClicked method, you can check the button that was clicked based on it's tag. Might want to keep constants around for what button is what.
For each of your buttons set an appropriate tag, and then refer to the tag in your action. i.e.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
...
button.tag = 1
[view addSubview:button];
You can easily set the tag based on the index of your iteration, if you're creating buttons in a loop. And then in your action:
- (void)aButtonWasTapped:(UIButton *)source {
if( source.tag == 1 ) {
// etc
}
}
Somebody might have this problem:
Jason Coco's answer worked fine for me, until I wanted to use the tag to access properties from an NSArray that was defined as a property.
Turns out the property had to be defined as "retain" instead of "weak".
The Swift version (with Labels):
for index in 1...5 {
var label = UILabel()
label.tag = index
labelsDictionary["Label\(index)"] = label
self.addSubview(label)
}
Call using using self.viewWithTag(i) as UILabel:
(cell.viewWithTag(5) as UILabel).text
I'm using 10 buttons in my interface and need, from time to time, to change the button's selector.
Am I required to use:
-(void)removeTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
before I change the selector or can I just use:
-(void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents
I'm concerned that if I change the selector using the addTarget: method sans the removeTarget: method that I'll essentially "stack up" selectors for my UIButton to fire when it is pressed.
Yes you should always remove the previously add target before assigning the new target to the button. Like this---
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(50, 50, 200, 50)];
[btn setTag:101];
[btn addTarget:self action:#selector(method1) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
btn = (UIButton *)[self.view viewWithTag:101];
[btn removeTarget:self action:#selector(method1) forControlEvents:UIControlEventTouchUpInside];
[btn addTarget:self action:#selector(method2) forControlEvents:UIControlEventTouchUpInside];
now if you do this
btn = (UIButton *)[self.view viewWithTag:101];
[btn addTarget:self action:#selector(method2) forControlEvents:UIControlEventTouchUpInside];
then both the methods method1 and method2 will be called.
Hope this helps.
Yes, you will need to remove the old target/action or both the old and new actions will be performed.
I am getting an error message displayed below when my button is pressed. I do not yet have any code inside my "buttonPressed" method although I don't think that has anything to do with it?
Error Message: "terminate called after throwing an instance of 'NSException'
Program received signal: "SIGABRT".
UIButton * myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setImage:[UIImage imageNamed:#"ButtonStandard.png"] forState:UIControlStateNormal];
[myButton setImage:[UIImage imageNamed:#"ButtonSelected.png"] forState:UIControlStateSelected];
[myButton setShowsTouchWhenHighlighted:YES];
myButton.frame = CGRectMake(0.0, 380.0, 320.0, 100.0);
[myButton addTarget:self action:#selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[contentView addSubview:myButton];
any help would be great.
Change the #selector(buttonPressed) to #selector(buttonPressed:) (note the colon at the end) and change the method itself to:
-(void)buttonPressed:(id)sender {
/* sender will be the UIButton. */
}