简体   繁体   中英

Set view programmatically. UIButtons added in UIView subclass. UIButtons visually show they are clicked but don't respond to selectors

Here is my code:

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        [self setupSubviewsWithContentFrame:frame];

        self.backgroundColor = [UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75];
        self.opaque = NO;

    }
    return self;
}

- (void)setupSubviewsWithContentFrame:(CGRect)frameRect 
{    
    // Get and set needed information for views/layout

    NSMutableDictionary *punchButtonDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Add a Punch", @"title", nil];
    // Create the selector
    SEL punchSelector = @selector(showScanner);
    // Add selector to the dictionary
    [punchButtonDict setObject:NSStringFromSelector(punchSelector) forKey:@"selectorKey"];

    // Create dictionary for email button
    NSMutableDictionary *okButtonDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"OK!", @"title", nil];
    // Create the selector
    SEL okSelector = @selector(hideView);
    // Add selector to the dictionary
    [okButtonDict setObject:NSStringFromSelector(okSelector) forKey:@"selectorKey"];

    // Create an array of the button dictionaries 
    blackButtons = [NSArray arrayWithObjects:punchButtonDict, okButtonDict, nil];

    // Count how many buttons are on this screen
    NSUInteger itemCount = blackButtons.count;

    // Stretchable image for counter background (placed here so it can be used for height)
    UIImage* counterBg =[[UIImage imageNamed:@"CounterStretchableBackground.png"]stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0];

    // Create a start x and y point for the view holder (to center it)
    int xPoint = ((self.bounds.size.width - SUBVIEW_WIDTH)/2);
    int yPoint = (((self.bounds.size.height - STATUS_BAR_HEIGHT) - (counterBg.size.height + (PADDING*(itemCount - 1)) + BUTTON_HEIGHT*itemCount)) / 2);

    // Setup each subview

    // First View viewHolder
    UIView *viewHolder = [[UIView alloc] init];
    // Get the height for viewHolder
    int viewHolderHeight = (counterBg.size.height + (PADDING*2) + (BUTTON_HEIGHT*itemCount));
    // Set the frame for the first view
    viewHolder.frame = CGRectMake(xPoint, yPoint, SUBVIEW_WIDTH, viewHolderHeight);

    // Create view for counter 
    UIImageView* counterView = [[UIImageView alloc] initWithImage:counterBg];
    // Set the frame to center (with respect to other buttons)
    counterView.frame = CGRectMake(0, 0, SUBVIEW_WIDTH, counterBg.size.height);

    // Create numberCount label (subview of counterView)
    _numberCount = [[UILabel alloc] initWithFrame:CGRectMake(0, COUNTER_PADDING, SUBVIEW_WIDTH, (((counterBg.size.height  - COUNTER_PADDING)/2)))];
    // Set label background to clear
    _numberCount.backgroundColor = [UIColor clearColor];
    // Set text
    _numberCount.text = @"0";
    // Set font
    _numberCount.font = [UIFont fontWithName:@"Oswald" size:32.0];
    // Set font color
    _numberCount.textColor = [UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:.9];
    // Set alignment
    _numberCount.textAlignment = UITextAlignmentCenter;
    // Set shadow color
    _numberCount.shadowColor = [UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:1.0];
    // Set shadow offset
    _numberCount.shadowOffset = CGSizeMake(0.0, 1.0);

    // Create numberCount label (subview of counterView)
    UILabel *punchesLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, (((counterBg.size.height)/2) + PADDING*2), SUBVIEW_WIDTH, 13)];
    // Set label background to clear
    punchesLabel.backgroundColor = [UIColor clearColor];
    // Set text
    punchesLabel.text = @"Punches";
    // Set font
    punchesLabel.font = [UIFont fontWithName:@"PTSans-Bold" size:13.0];
    // Set font color
    punchesLabel.textColor = [UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:.9];
    // Set alignment
    punchesLabel.textAlignment = UITextAlignmentCenter;
    // Set shadow color
    punchesLabel.shadowColor = [UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:1.0];
    // Set shadow offset
    punchesLabel.shadowOffset = CGSizeMake(0.0, 1.0);

    // Create toGoLabel (subview of counterView)
    _toGoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, (((counterBg.size.height)/2) + PADDING*3 + punchesLabel.frame.size.height), SUBVIEW_WIDTH, 12)];
    // Set label background to clear
    _toGoLabel.backgroundColor = [UIColor clearColor];
    // Set text
    _toGoLabel.text = @"7 more to go!";
    // Set font
    _toGoLabel.font = [UIFont fontWithName:@"PTSans-Regular" size:11.0];
    // Set font color
    _toGoLabel.textColor = [UIColor colorWithRed:240.0f/255.0 green:240.0f/255.0 blue:240.0f/255.0 alpha:.9];
    // Set alignment
    _toGoLabel.textAlignment = UITextAlignmentCenter;
    // Set shadow color
    _toGoLabel.shadowColor = [UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:1.0];
    // Set shadow offset
    _toGoLabel.shadowOffset = CGSizeMake(0.0, 1.0);


    // Add views in proper order and location

    [self addSubview:viewHolder];

    [viewHolder addSubview:counterView];

    [counterView addSubview:_numberCount];

    [counterView addSubview:punchesLabel];

    [counterView addSubview:_toGoLabel];


    // First button y start point
    int buttonY = counterBg.size.height + PADDING;
    // Stretchable image for counter background (placed here so it can be used for height)
    UIImage* blackButton =[[UIImage imageNamed:@"UIButtonBlack.png"]stretchableImageWithLeftCapWidth:10.0 topCapHeight:0.0];

    // Iterate through each item
    for (NSUInteger i = 0 ; i < itemCount ; i++)
    {


        // Get the right data
        NSDictionary* data = [blackButtons objectAtIndex:i];
        // Return the title for this button
        NSString *buttonText = [data objectForKey:@"title"];

        SEL buttonSelector = NSSelectorFromString([data objectForKey:@"selectorKey"]);

        NSLog(@"%@", [data objectForKey:@"selectorKey"]);

        // Create button frame
        CGRect buttonFrame = CGRectMake(0, buttonY, SUBVIEW_WIDTH, BUTTON_HEIGHT);

        UIButton *newButton;

        UIImage *iconImage = [UIImage imageNamed:@"EmailIcon.png"];

        newButton = [self buttonWithTitle:buttonText target:self selector:buttonSelector frame:buttonFrame image:blackButton insertImage:iconImage];

        [self addSubview:newButton];

        buttonY += (PADDING + BUTTON_HEIGHT);

    }

//    for (UIView *view in self.subviews)
//
//    view.userInteractionEnabled=NO;


    [self setNeedsDisplay];

}

- (UIButton *)buttonWithTitle:(NSString *)title target:(id)target selector:(SEL)inSelector frame:(CGRect)frame image:(UIImage*)image insertImage:(UIImage*)insertImage
{
    // Create button
    UIButton *button = [[UIButton alloc] initWithFrame:frame];

    // Set button content alignment
    button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;

    // Set button title
    [button setTitle:title forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
    // Set button title color
    [button setTitleColor:[UIColor colorWithRed:255.0f/255.0 green:255.0f/255.0 blue:255.0f/255.0 alpha:1.0] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];
    // Add the background image
    [button setBackgroundImage:image forState:UIControlStateNormal];
    // Add Events
    [button addTarget:target action:inSelector forControlEvents:UIControlEventTouchUpInside & UIControlEventTouchDown];
    // in case the parent view draws with a custom color or gradient, use a transparent color
    [button setBackgroundColor:[UIColor clearColor]];  
    // Set titleShadowColor this way (apparently, titleLabel.shadowcolor does not work)
    [button setTitleShadowColor:[UIColor colorWithRed:0.0f/255.0 green:0.0f/255.0 blue:0.0f/255.0 alpha:.75] forState:UIControlStateNormal & UIControlStateHighlighted & UIControlStateSelected];

    // Set button titleLabel properties  
    button.titleLabel.font = [UIFont fontWithName:@"PTSans-Bold" size:13.0];
    button.titleLabel.shadowOffset = CGSizeMake(1, 1);    

    // If there is an insertImage icon
    if(insertImage != nil) 
    {
        // padding between image and text
        int seperate = 6; 
        // Image and title frame (used to center text/image)
        int width = (button.titleLabel.frame.size.width + insertImage.size.width + seperate);
        int buttonWidth = button.frame.size.width;
        int xPadding = (buttonWidth - width)/2;
        int yPadding = (button.frame.size.height - insertImage.size.height)/2;

        // Create an image view for the image (standard icon is 12x13)
        UIImageView *insertImageView = [[UIImageView alloc] initWithFrame:CGRectMake(xPadding, yPadding, insertImage.size.width, insertImage.size.height)];
        // add the insertImage to the view
        [insertImageView setImage:insertImage];
        // add the insertImageView to the button
        [button addSubview:insertImageView];
        // Add offset with title
        button.titleEdgeInsets = UIEdgeInsetsMake(BUTTON_VERTICAL_INSET, insertImage.size.width + seperate, 0, 0);
    }
    else 
    {
        // No image so no horizontal offset but PTSans font needs a 2 vertical offset
        button.titleEdgeInsets = UIEdgeInsetsMake(BUTTON_VERTICAL_INSET, 0, 0, 0);
    }
    return button;
}

This is how I set the view to it's view controller

rewardsView = [[RewardsView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
self.view = rewardsView;

In your NSLog you should not check what selector string is stored in your data dictionary but if the SEL variable contains the correct selector.

I strongly recommend simplifying the code. The approach to store the parameters of the buttons in an array of dictionaries is quite error prone. You end up with way to many parameters. Finding an error like yours (selector does not fire) becomes much more difficult than necessary.

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