With a loop I add UIImageView to a UIScrollView i need to add an extra parameter addTarget so when i click i can log the index.
[imageButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
-(IBaction) buttonPushed: (int) index
{
NSLog(#"%d",index);
}
How do i achieve this?
When you add a target, the method being call can either have no arguments (e.g. buttonPushed) or have one (buttonPushed:) which is the control sending the event (in this case your button). If you want an index, or any other value, you need to set it on the button sending the event. For example, when you setup the buttons:
myButtons = [NSArray arrayWithObjects:myFirstButton, mySecondButton, nil];
[myFirstButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
[mySecondButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
and implement your action as
- (IBaction)buttonPushed:(UIButton *)button
{
NSLog(#"%d",[myButtons indexOfObject:button]);
}
Use the tag property of the button
Related
I have a button name "button1"
i have given a selector for it as below
[button1 addTarget:self action:#selector(buttonPressedMethod:) forControlEvents:UIControlEventTouchUpInside];
now after i have done execution of certain codes. i want this method "buttonPressedMethod:" to be no longer involved in the play.
i want to assign a different selector method. say
[button1 addTarget:self action:#selector(dummymethod:) forControlEvents:UIControlEventTouchUpInside];
What i am getting now is.
Both the methods are called. i want only one method to be called at a time.
Please give some suggestions to cancel a selector method.
remove your first target before adding the new one:
[button1 removeTarget:self action:#selector(buttonPressedMethod:) forControlEvents:UIControlEventTouchUpInside];
Just try it simple. Create a method and addtarget to the button1 then there do the conditional checkup to call another method like
-(void)button1Clicked:(id)sender{
if(check_your_Condition==true) { [self previousMethod];}
else { [self laterMethod];}
}
have a variable to track current action of the button.
SEL currentAction;
// assign action to button using this
currentAction = #selector (newAction:);
[button1 addTarget: self action: currentAction forControlEvents: UIControlEventTouchUpInside];
// remove previous action action before assigning new one
if (currentAction)
{
[button1 removeTarget: self action: currentAction forControlEvents: UIControlEventTouchUpInside];
}
// and then reassign action like explained above
Maintain one boolean flag . When you want call first selector :
if(flag==True)
{
[button1 addTarget:self action:#selector(buttonPressedMethod:) forControlEvents:UIControlEventTouchUpInside];
}
After that make flag false where you want.
if(flag==false)
{
[button1 addTarget:self action:#selector(dummymethod:) forControlEvents:UIControlEventTouchUpInside];
}
I have changed button title of a UIButton programmatically. I have also assigned an action to changed button title. Now when i tap on the button, it triggers both the action (one with same button title and one with changed). However, i want to trigger only one action for the changed title button.
How can i do it? Any help would be appreciated.
Two solutions. Toggle the target/action between methods or decide what to do based on some state.
1.
- (void)method1:(id)sender;
{
[sender removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside];
[sender addTarget:self action:#selector(method2:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)method2:(id)sender;
{
[sender removeTarget:nil action:NULL forControlEvents:UIControlEventTouchUpInside];
[sender addTarget:self action:#selector(method1:) forControlEvents:UIControlEventTouchUpInside];
}
2a.
- (void)buttonTapped;
{
if (self.someState) {
} else {
}
}
2b.
- (void)buttonTapped:(UIButton *)button;
{
if ([[button titleForState:UIControlStateNormal] isEqualToString:#"First title"]) {
} else {
}
}
if you assign two actions for the same button for control state touchupinside, it will always trigger both.You should remove the first action while adding the second and remove second itself and add the first again at the end of selector function.
The following is the default action of the button;
[button addTarget:self:action:#selector(actionOne)forControlEvents:UIControlStateTouchUpInside]
In the actionOne you can call remove observer for the first action and add the second one.
[button addTarget:self:action:#selector(actionTwo)forControlEvents:UIControlStateTouchUpInside]
And in actionTwo function you do the reverse
Instead of making two conditions
f([urlresponse status code] == 200)
{
[myButton setTitle:#"Unfollow" forState:UIControlStateNormal]; //title changed
[myButton addTarget:self action:#selector(unfollowButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
It might be helpful for your case.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Arguments in #selector
This is probably a really simple question, but I need a really good answer...
Using the following code I can call a method when a button is clicked...
[pushButton addTarget:self action:#selector(pushOrPull:andVI:) forControlEvents:UIControlEventTouchUpInside];
[pullButton addTarget:self action:#selector(pushOrPull:andVI:) forControlEvents:UIControlEventTouchUpInside];
The method is below...
-(void) pushOrPull: (int)pushPull andVI: (NSString *) videoId {
}
I want the buttons to be able to supply arguments to that method, but when I try this...
[pushButton addTarget:self action:#selector(pushOrPull:2 andVI:#"someVID") forControlEvents:UIControlEventTouchUpInside];
[pullButton addTarget:self action:#selector(pushOrPull:1 andVI:#"someVID") forControlEvents:UIControlEventTouchUpInside];
Xcode gives me two errors: "expected )"
How can I supply these two arguments to the method when my buttons get tapped?
What you could do is just have a method in the middle.
[pushButton addTarget:self action:#selector(runMyMethod) forControlEvents:UIControlEventTouchUpInside];
pushButton.tag =0;
[pullButton addTarget:self action:#selector(runMyMethod) forControlEvents:UIControlEventTouchUpInside];
pullbutton.tag =1;
-(void) runMyMethod:(id)sender {
if(sender.tag ==0)
{
[self pushOrPull:1 andVI:#"someVID"];
}
else if (sender.tag ==1)
{
[self pushOrPull:2 andVI:#"someVID"];
}
}
-(void) pushOrPull: (int)pushPull andVI: (NSString *) videoId {
}
Unfortunately, you can't. Buttons only "know how" to send themselves as the first argument. The best bet is to have the buttons "belong" to some view controller (to which they send their events) which can interpret the button press, and then call a delegate method elsewhere with as many arguments as you need.
To answer a related question, a "selector" never carries actual arguments, but it does carry one colon per argument: #selector(aMethodWithThis:andThat:)
This is a bit better:
// set up an NSMutableDictionary, videoIDsForButtons as an iVar or property
[pushButton addTarget:self action:#selector(buttonWasPressed:) forControlEvents:UIControlEventTouchUpInside];
[videoIDsForButtons setObject: #"someVID" forKey: pushButton];
[pullButton addTarget:self action:#selector(buttonWasPressed:) forControlEvents:UIControlEventTouchUpInside];
[videoIDsForButtons setObject: #"someVID" forKey: pullButton];
- (void)buttonWasPressed:(id)sender
{
if (sender == pushButton)
{
[self pushOrPull: 2 andVI: [videoIDsForButtons objectForKey: sender]];
}
else // assume pullButton
{
[self pushOrPull: 1 andVI: [videoIDsForButtons objectForKey: sender]];
}
}
This is because selectors don't take arguments, only method calls do. And when a button is pressed, it supplies itself as the only argument (sender). You should have a whole separate responder method that looks at sender and determines the appropriate recourse.
unfortunately the -addTarget:action:forControlEvents: can call back you via the following method with the next parameters only:
-(IBAction)selector:(id)sender forEvent:(UIEvent *)event;
so, you should check inside this method which object fired the event (sender), and after it, still inside this method you can call your own -pushOrPull:andVI: method with the desired parameters, or you can set two different callback methods as well and then you won't have to check the sender parameter, just call your -pushOrPull:andVI: like this:
{
// ...
[pushButton addTarget:self action:#selector(pushButtonTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
[pullButton addTarget:self action:#selector(pullButtonTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
// ...
}
- (IBAction)pushButtonTouchedUpInside:(id)sender {
[self pushOrPull:2 andVI:#"someVID"];
}
- (IBAction)pullButtonTouchedUpInside:(id)sender {
[self pushOrPull:1 andVI:#"someVID"];
}
Good Evening all!
I have some UIButtons added dynamically into my view and of course I have an IBAction which handles button events.
The problem is: How can I detect which button is pressed if the only thing I know is the (id)sender and the array of buttons?
Buttons are never the same, every button has a different behavior. When I want to use static buttons and connect them through the IB I use something like this :
-(IBAction)doSomething:(id)sender
{
if(sender == button1)
dosomething;
if(sender == button2)
dosomething else;
if(sender == button3)
dosomething3;
}
In my case this does not work because there is no button1, button2, button3 but a MutableArray of buttons which have the same name as they were allocated with it. Button!
I tried using the way above but with no success and i tried also getting the tag of a button but I have nothing to compare it to!
I would really appreciate your help.
sincerely
L_Sonic
PS Dynamicaly means that i am creating the buttons in random time during run time like this
-(void)configActionSheetView
{
buttonView = [[UIView alloc]initWithFrame:CGRectMake(0.0,460, 60, 480)];
[buttonView setBackgroundColor:[UIColor blackColor]];
[buttonView setAlpha:0.6];
for (int i = 0 ;i<[buffButtons count];i++)
{
UIButton *customButton = [buffButtons objectAtIndex:i];
customButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//UILabel *customLabel = [[UILabel alloc]init];
//[customButton setTag:(i)+11];
[customButton addTarget:self action:#selector(activateBuffEffect:) forControlEvents:UIControlEventTouchUpInside];
[customButton setAlpha:1.0];
customButton.frame = CGRectMake(8.0, 5+(50*i), 44.0, 44.0);
[customButton setTitle:nil forState:UIControlStateNormal];
buttonView.frame = CGRectMake(0, 460, 60, 50+(44*(i+1)));
[buttonView addSubview:customButton];
}
}
this is inside a functions and gets called during run time. the buffButtons is a mutableArray with buttons that gets populated during runtime.
i need a solution like this i cannot get a different eventhandling method for everybutton.
When you was "added dynamically" I assume you mean that they are created from some piece of code. Since all buttons to different things and you know what a certain button should do, why don't you add different actions to different buttons?
UIButton *myCreatedButton = [[UIButton alloc] init];
[myCreatedButton addTarget:self
action:#selector(doSomething:)
forControlEvents:UIControlEventTouchUpInside];
UIButton *myOtherCreatedButton = [[UIButton alloc] init];
[myOtherCreatedButton addTarget:self
action:#selector(doSomethingElse:)
forControlEvents:UIControlEventTouchUpInside];
In the above code the target (set to self) is the class where the method you want to run is found, the action is the method that you want to run and the controlEvent is what should cause the method to run.
If you did it like this you would split the code in different methods like these (you do not need to specify them in the header):
-(void)doSomething:(id)sender {
// do somthing here ...
}
-(void)doSomethingElse:(id)sender {
// do somthing else here ...
}
This way you don't need to know what button was pressed since the correct code would get called anyway. Besides it makes it cleaner if you need to change the code for some of the buttons.
Found it!
-(IBAction)buttonTapped:(id)sender {
UIButton *btn = (UIButton *)sender;
NSLog(#"tapped: %#", btn.titleLabel.text);
[self anotherIBAction:sender];
}
now i can get the tag from the btn :D
thnk you!
Why not add a tag the button and then get the tag number from (id)sender in the selector function?
i am having a application where i am generating the uibuttons dynamically want to use same #selector...Now as sooon as event is generated i wanna check for values and pass it to thtroughthat selector how can i implement this code?
can anyone tell me a tutorial sort where buttons are dynamically generated and check for particular button click is depicted?
Plz help...
Not sure what do you call "dynamically"... Objective-c objects are always created dynamically. Perhaps you mean situation where you want to create series of very similar buttons with same code? Yes, it is quite a common task. For example in calculator like app, we need ten buttons with digits, why not create them with single block of code ? So:
- (void)makeButtons{
UIButton * aButton;
for(int i = 0; i < 10; i++){
aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.frame = CGRectMake(0, i*45, 60, 40);
[aButton addTarget:self action:#selector(digitClick:) forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:[NSString stringWithFormat:#"%d",i] forState:UIControlStateNormal];
aButton.tag = i;
[self.view addSubview:aButton];
}
}
- (void)digitClick:(id)sender{
UIButton * aButton =(UIButton *)sender;
NSLog(#"cliced button with title %d",aButton.tag);
}
we use a tag property to find index of clicked button, it is often used way, but there are some other ways. For example store created buttons in array and then check if sender is equal to one of array elements:
...
if ([allButtons objectAtIndex:i] == sender)
...
If you want to pass some data, for example string from each button just create array with these objects and then access it using tag as index.
Try:
[self.button1 addTarget:self action:#selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
[self.button2 addTarget:self action:#selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
- (IBAction)buttonTouchDown:(id)sender
{
if (sender == self.button1) NSLog(#"Button-1");
if (sender == self.button2) NSLog(#"Button-2");
}