36

In my project I must control action of 40 buttons, but I don't want to create 40 IBAction, can I use only a IBAction, how?

Braiam
  • 1
  • 11
  • 47
  • 78
cyclingIsBetter
  • 17,447
  • 50
  • 156
  • 241
  • 1
    possible duplicate of [How to define which button pressed if they both have same IBAction?](http://stackoverflow.com/questions/5542327/how-to-define-which-button-pressed-if-they-both-have-same-ibaction) – Caleb May 02 '11 at 14:23
  • Follow this answer..http://stackoverflow.com/questions/16050516/how-to-connect-multiple-buttons-in-a-storyboard-to-a-single-action/24842728#24842728 – Tunvir Rahman Tusher Jul 26 '14 at 07:20

7 Answers7

56

If you're using interface builder to create the buttons, simply point them at the same IBAction in the relevant class.

You can then differentiate between the buttons within the IBAction method either by reading the text from the button...

- (IBAction)buttonClicked:(id)sender {
    NSLog(@"Button pressed: %@", [sender currentTitle]);    
}

...or by setting the tag property in Xcode and reading it back via [sender tag]. (If you use this approach, start the tags at 1, as 0 is the default and hence of little use.)

John Parker
  • 54,048
  • 11
  • 129
  • 129
  • 10
    In Xcode 4.6 using storyboards there is a bug, it will not allow additional connections. Just make all the connections from the button to the code (adding the `IBACTION` method and then delete all but one. – zaph Feb 22 '13 at 20:49
  • 6
    Just realized that you can also multiselect all the UIButtons that you have created in IB by holding CMD and selecting them all, then ctrl-drag that to the code, and it will create a single IBAction with all the UIButtons connected to it. – codeqi Mar 22 '13 at 15:57
12
-(IBAction)myButtonAction:(id)sender {
    if ([sender tag] == 0) {
        // do something here
    }
    if ([sender tag] == 1) {
        // Do something here
    }    
}

// in Other words

-(IBAction)myButtonAction:(id)sender {
        switch ([sender tag]) {
        case 0:
            // Do something here
            break;
        case 1:
           // Do something here
             break;
       default:
           NSLog(@"Default Message here");
            break;
}
David
  • 3,285
  • 1
  • 37
  • 54
BigAppleBump
  • 1,096
  • 12
  • 26
  • 1
    Would recommend a switch statement and a typedef enum for each tag for clarity if using this approach. – Tim Apr 15 '13 at 13:28
9

Set all the buttons to use that one action. Actions generally have a sender parameter, which you can use to figure out which button is calling the action. One popular way to tell the difference between buttons is to assign a different value to each button's tag property. So you might have 40 buttons with tags ranging from 1 to 40. (0 probably isn't a great choice for a tag since that's what the default value is, and any button for which you forget to set the tag will have 0 as the tag value.)

This technique is most useful when all the buttons do approximately the same thing, like the buttons on a calculator or keyboard. If each of the buttons does something completely different, then you still end up with the equivalent of 40 methods, but you substitute your own switch statement for Objective-C's messaging system. In that case, it's often better just to spend the time to create as many actions as you need an assign them appropriately.

Caleb
  • 124,013
  • 19
  • 183
  • 272
4

Sure. Just connect all buttons to the same action method in Interface Builder. Use the method's sender argument (possibly in conjunction with the buttons' tag property) to identify which button is sending the event.

Ole Begemann
  • 135,006
  • 31
  • 278
  • 256
0

Just used the above method myself , had a selection of buttons but converted them all and used switch case instead

-(IBAction)buttons:(id)sender
{

    switch ([sender tag])

    {

        case 0 :

    }
}
Jitendra
  • 5,055
  • 2
  • 22
  • 42
clive dancey
  • 143
  • 11
  • It if were me, I would have separate actions for each button, and extract the common code into a separate method, called from each button action method. In doing so you make the code much cleaner with a single button<->action relationship for each and avoid the use of a switch, which is often a code smell. – Michael Apr 28 '13 at 11:44
  • its really unfair being voted down when you are only trying to help someone out...sometimes answers are so convoluted we need something simple in order to get the point of what we are asking. – clive dancey Apr 29 '13 at 12:22
0

Seems like you are getting all the answers you need, but I wanted to add to everyone else's answers.

Whether you want to use one IBAction or 40 actions is up to what you want the buttons to do. If all the buttons do completely different things, you need all separate IBActions, but if you want all of them to do the same thing, you can use just one. I need more details of those buttons and action, but you probably have title for each button, so you can use that to differentiate each button and create a message or something that's being customized by the particular button pressed. Here is the example. Each time a button is pressed, a label displays a message that say "i.e.title of the button" pressed.

By doing it this way, you don't need to do switch case with all 40 patterns. You can still display or do something that's individualized by the button pressed with just 2-3 lines of code.

- (IBAction)button_Clicked:(UIButton *)sender {

    //Get the buttons' titles.
    NSString *title =[sender titleForState:UIControlStateNormal];

    //Construct a message that includes the *title. 
    NSString *plainText=[NSString stringWithFormat:@"%@ button pressed.", title];

    //Assigns the *plainText to the label. 
    self.Label.text=plainText;

}
@end
0

Just use one IBAction and assign it to all your buttons.

Joris Mans
  • 6,024
  • 6
  • 42
  • 69