John Snurr John Snurr - 6 months ago 9
iOS Question

Deselect all UIButtons when one is selected

I'm going to try to explain this the best that I can, so bare with me. I have eight (8) UIButtons setup in my game. When one is selected it shows that it is selected and if you click it again it will show as unselected. However, I want to make it so that when you select a button and any of the other seven (7) are selected, they become unselected.

I know how to do this through the use of

[buttonName setSelected:NO]
but the problem is I can't pass buttonOne to buttonTwo if buttonTwo has already been passed to buttonOne because I have already imported buttonTwo's header file in buttonOne. It throws a parse error if I have both headers importing each other. I've been stuck on this for a while now and was hoping that someone might have a solution to my problem.

Thanks for any help.

Answer

I actually created an answer by reading all of your guys input, which I thank you greatly for. The tag property of the UIButton class was unknown to me before this post.

I created own subclass of UIButton, let's call it CustomUIButton.m. I created a NSMutableArray property for use when storing the buttons, which I'll call customButtonArray.

When I created the button, I set the tag property, and added the button to a local array on the parent view controller. After all buttons I wanted were created, I set the customButtonArray, like so:

// Initialize buttonHolderArray
NSMutableArray *buttonHolderArray = [[NSMutableArray alloc] init];

// Create a button
CustomUIButton *newButton = [[CustomUIButton alloc] initWithFrame:CGRectMake(10, 10, 50, 30)];
newButton.tag = 1;
[newButton setImage:[UIImage imageNamed:@"newButtonUnselected" forControlState:UIControlStateNormal]];
[buttonHolderArray addObject:newButton];

// Create additional buttons and add to buttonHolderArray...
// using different numbers for their tags (i.e. 2, 3, 4, etc)

// Set customButtonArray property by iterating through buttonHolderArray
NSInteger buttonCount = [buttonHolderArray count];

for (int i = 0; i < buttonCount; i++)
{
   [[buttonHolderArray objectAtIndex:i] setCustomButtonArray:buttonHolderArray];
}

To deselect any other button selected when a different buttons handleTap: is called, I iterated through the customButtonArray in the subclass main file and set the selected property to NO. I also set the correct image from another array property that I manually populated with the images, which I did so the array didn't have to be populated every time a button was pressed. At the end, unselected all other buttons, like so:

// Populate two arrays: one with selected button images and the other with
// unselected button images that correspond to the buttons index in the 
// customButtonArray
NSMutableArray *tempSelectedArray = [[NSMutableArray alloc] init];
[tempSelectedArray addObject:[UIImage imageNamed:@"newButtonSelected"]];
// Add the other selected button images...
// Set the property array with this array
[self setSelectedImagesArray:tempSelectedArray];

NSMutableArray *tempUnselectedArray = [[NSMutableArray alloc] init];
[tempUnselectedArray addObject:[UIImage imageNamed:@"newButtonUnselected"]];
// Add the other unselected button images...
// Set the property array with this array
[self setUnselectedImagesArray:tempUnselectedArray];

- (void)handleTap:(UIGestureRecognizer *)selector
{
    // Get the count of buttons stored in the customButtonArray, use an if-elseif
    // statement to check if the button is already selected or not, and iterate through
    // the customButtonArray to find the button and set its properties
    NSInteger buttonCount = [[self customButtonArray] count];

    if (self.selected == YES)
    {
        for (int i = 0; i < buttonCount; i++)
        {
            if (self.tag == i)
            {
                [self setSelected:NO];
                [self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
            }
        }
    }
    else if (self.selected == NO)
    {
        for (int i = 0; i < buttonCount; i++)
        {
            if (self.tag == i)
            {
                [self setSelected:NO];
                [self setImage:[[self selectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
            }
        }
    }

    for (int i = 0; i < buttonCount; i++)
    {
        if (self.tag != i)
        {
            [self setSelected:NO];
            [self setImage:[[self unselectedImagesArray] objectAtIndex:i] forControlState:UIControlStateNormal];
        }
    }
}

Thanks for all of the useful information though, figured I should share the final answer I came up with in detail to help anyone else that comes across this problem.