简体   繁体   中英

UIButton not calling target's selector

I have a button that doesn't call its target's selector.

When I click it, it does get highlighted. However, I set a break point at playButtonClicked and it never gets reached.

I'm not sure if it's being released, but I don't think so. I have ARC enabled and I can't call retain or release .

I've also tried explicitly enabling userInteractionEnabled but that doesn't make a difference either.

Here is my code:

#import "MainMenuView.h"
@implementation MainMenuView
- (void)initializeButton:(UIButton*)button withText:(NSString*)text buttonHeight:   (int)buttonHeight buttonWidth:(int)buttonWidth buttonYInitialPosition:(int)buttonYInitialPosition buttonXPosition:(int)buttonXPosition
{
    button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(buttonXPosition, buttonYInitialPosition, buttonWidth, buttonHeight);

    button.backgroundColor = [UIColor clearColor];
    [button setBackgroundImage:[UIImage imageNamed:@"button.png"] forState:UIControlStateNormal];

    [button setTitle:text forState:UIControlStateNormal];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    button.titleLabel.font = [UIFont boldSystemFontOfSize:24];
    [self addSubview:button];
    [self bringSubviewToFront:button];
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {        
        self.backgroundColor = [UIColor yellowColor];

        UIImage *backgroundImage = [UIImage imageNamed:@"title_background.jpeg"];
        UIImageView *background = [[UIImageView alloc] initWithFrame:frame];
        background.image = backgroundImage;
        background.backgroundColor = [UIColor greenColor];
        [self addSubview:background];

        int centerWidth = frame.size.width / 2;
        int centerHeight = frame.size.height / 9;
        int centerXPos = frame.size.width / 4;
        int buttonYInitialPosition = frame.size.height / 2 + frame.size.height / 20;
        int buttonYOffset = frame.size.height / 7;

        // init buttons
        [self initializeButton:playButton withText:@"Play" buttonHeight:centerHeight buttonWidth: centerWidth
        buttonYInitialPosition:buttonYInitialPosition buttonXPosition:centerXPos];
        [playButton addTarget:self action:@selector(playButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
}
- (void) playButtonClicked:(id)sender
{
    NSLog(@"Play Button Clicked");
}
@end

Your code isn't doing what you think it is.

When you pass playButton in to -initializeButton:... and then immediately create a new button and assign it to that variable, you're no longer operating on the value that playButton points to. So when you call -addTarget:action:forControlState: afterwards, you're assigning a target to whatever playButton happens to point to, which is not the button you just created and added.

Passing a pointer is done (by default) by value , which means that you only have the address that the pointer held, not a reference to the pointer itself. So you can't change the pointer itself, only the object it points to. You can pass the pointer by reference , if you want to modify what it points to; or you can restructure your code so that you're always acting on the pointer directly—for instance, you could just use an ivar or property and have your initialize method set that property. Or you could return the button and assign it to your variable or property.

You are initializing the button incorrectly. A better approach is to have your initializeButton return the button.

- (UIButton *)initializeButtonWithText:(NSString*)text buttonHeight:   (int)buttonHeight buttonWidth:(int)buttonWidth buttonYInitialPosition:(int)buttonYInitialPosition buttonXPosition:(int)buttonXPosition
{
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(buttonXPosition, buttonYInitialPosition, buttonWidth, buttonHeight);

    button.backgroundColor = [UIColor clearColor];
    [button setBackgroundImage:[UIImage imageNamed:@"button.png"] forState:UIControlStateNormal];

    [button setTitle:text forState:UIControlStateNormal];
    [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    button.titleLabel.font = [UIFont boldSystemFontOfSize:24];
    [self addSubview:button];
    [self bringSubviewToFront:button];

    return button;
}

Then call it this way:

playButton = [self initializeButtonWithText:@"Play" buttonHeight:centerHeight buttonWidth: centerWidth
    buttonYInitialPosition:buttonYInitialPosition buttonXPosition:centerXPos];

I think you should do your initialization stuff in the method:

-(void)awakeFromNib {}

It's like the -viewDidLoad method for custom UIViews in that all the nib objects have been loaded and ready to go.

In the first line of your initializeButton method, you create a new Button. This new button is styled and added to the view hierarchy. This is the button that you see and that you can tap when you launch your app.

However, you apparently have another button named playButton . You pass it into the initializeButton method, but as written above, don't do anything with that reference. That means the addTarget: call goes to a button that you never add to your view hierarchy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM