1

I have created a several buttons like this:

[self makeButtonsWithX:0.0f y:180.0f width:640.0f height:80.0f color:[UIColor colorWithRed:0.796 green:0.282 blue:0.196 alpha:1] button:self.redButton];

    [self makeButtonsWithX:0.0f y:260.0f width:640.0f height:80.0f color:[UIColor colorWithRed:0.761 green:0.631 blue:0.184 alpha:1] button:self.yellowButton];

using this function:

- (void)makeButtonsWithX:(CGFloat)x y:(CGFloat)y width:(CGFloat)width height:(CGFloat)height color:(UIColor *)color button:(UIButton *)button
{
    button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(x, y, width, height);
    button.backgroundColor = color;
    [self.view addSubview:button];

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

When I tap one of them I want to know which one was tapped, using this function:

- (void)tappedButton:(UIButton *)button
{
    //NSLog(@"tapped");
    if ([button isEqual:self.redButton]) {
        NSLog(@"Red");
    }
}

Nothing happens. If I uncomment the first NSLog in the last function however, it prints every time I press a button (doesn't matter which one). Why isn't my if-statement working?

Cheers.

Nilzone-
  • 2,766
  • 6
  • 35
  • 71

2 Answers2

2

When you're creating the buttons, give them unique tags.

Change your tappedButton: method to this:

- (void)tappedButton:(id)sender {
    if([sender tag] == 1) {
        NSLog(@"Red");
    }
}

And I'd probably create an enum for the tags:

typedef NS_ENUM(NSUInteger, ButtonTags) {
    ButtonUnknown = 100,
    ButtonRedTag = 101,
    ButtonBlueTag = 102,
    ButtonGreenTag = 103,
    ButtonYellowTag = 104,
    ButtonWhiteTag = 105
};

Now use the enum both when setting and checking the tags.

if([sender tag] == ButtonRedTag)

To set a tag:

[button setTag:ButtonRedTag];

There may be another way of determine which button was pressed, but as far as I'm concerned, using [sender tag]; is the best method. Consider this... suppose you want to call a method either when a button is pressed or a text field has resigned first responder? For example, imagine a login page, with a username/password text field and a button for login and create new account. Using sender tag, you can EASILY make all your UI elements at least start in the same method:

- (void)handleUserInteraction:(id)sender {
    switch([sender tag]) {
        case LoginButtonTag:
            // do stuff
            break;
        case PasswordTextFieldTag:
            // do stuff
            break;
        case NewAccountButtonTag:
            // do stuff
            break;
        case BackgroundViewTappedTag:
            // do stuff
            break;
    }
}

It might make more sense to just hook all of these UI elements up to different methods in the first place, and certainly, within the switch, they should call out to different methods, but suppose there's some bit of logic you want to execute in all 4 of these cases? Put it just before or just after the switch instead of putting it in all 4 of the methods you've created for handling these different cases, etc.

nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • Nice one! Thanks :) But do you know why my function don't work the way it is? isEqual is comparing two uibutton objects? – Nilzone- Jan 18 '14 at 14:27
  • According to this StackOverflow answer, `isEqual:` always returns false for `UIButton`. http://stackoverflow.com/a/14036622/2792531 Anyway, there may be another way to compare buttons, but using tags really is the best way to determine which UI element we're looking at. – nhgrif Jan 18 '14 at 14:28
  • @Nilzone- I added an edit explaining why you might want to get into the habit of using `[sender tag]` even for ui elements that might be comparable using `[foo isEqual:bar]`. – nhgrif Jan 18 '14 at 14:38
  • I'm new to IOS programming. Where would it be appropriate to put the NSEnum? – Nilzone- Jan 18 '14 at 14:46
  • Right after the `#import` lines in the `.m` file. Also, the first word should be `typedef`, not just `type`. – nhgrif Jan 18 '14 at 14:46
  • thanks! one last probably silly question. Why would you start at 100, 101 etc.. or is that completely random? – Nilzone- Jan 18 '14 at 14:49
  • Somewhat random. I don't start at 0 for tags. But basically, I might make my button tags be 100-105, my text field tags are 200-210, etc. Each type of UIElement starts at a different increment of 100. And it's just my personal preference. – nhgrif Jan 18 '14 at 14:50
  • What's wrong with `button === self.redButton`? Simple and readable. – Sulthan Jan 18 '14 at 15:47
  • First, there's no `===`. Second, enumerated tags is just as readable. Third, you can't use a switch on a button, but you can on a tag (and switches increase readability versus an if/else structure in my opinion). – nhgrif Jan 18 '14 at 17:45
0

In addition, you cannot pass the button "to make" by reference. The way you call makeButtonsWithX will to not change self.redButton.
self.redButton in the if statement will be nil.
Change the return type of make ButtonsWithX from (void)to (UIButton *) and do it like this:

self.redButton = [self makeButtonsWithX: ...
user3071962
  • 320
  • 3
  • 8