UIButton Doesn't Reload When Added to Cells ContentView

Discussion in 'iOS Development' started by Steaps, Jul 10, 2009.

  1. Steaps

    Steaps New Member

    Joined:
    Oct 24, 2007
    Messages:
    5,074
    Likes Received:
    41
    Device:
    iPod touch
    I have a UITableView that I have a UIButton set to the accessoryView of each cell.
    When you touch the button, it calls a method to change the image on the button. Everything works, when you have the button set to the accessoryView (cell.accessoryView = button).

    But i'm looking to have the button set to the contentView ([cell.contentView addSubview:button]), so I can have it on the left side of the cell. But when the button is a subview of the contentView, the buttons image doesn't reload.

    Any help?

    Here's the related code:

    How the array is set up:
    Code:
    array = [[NSMutableArray alloc] init];
    for(int i = 0; i <= 10; i++) {
    	NSArray * aArray = [[NSArray alloc] initWithObjects:[NSString stringWithFormat:@"%d", i], @"unchecked", nil];
    	[array addObject:aArray];
    	[aArray release];
    }
    
    In the tableView's rowAtIndexPath method:
    Code:
    UIImage * image = ([[[array objectAtIndex:indexPath.row] objectAtIndex:1] isEqualToString:@"checked"]) ? [UIImage imageNamed:@"checked.png"] : [UIImage imageNamed:@"unchecked.png"];
    UIButton * checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
    checkButton.frame = CGRectMake(0, 0, image.size.width, image.size.height);
    [checkButton setBackgroundImage:image forState:UIControlStateNormal];
    [checkButton addTarget:self action:@selector(checkButtonTapped:event:) forControlEvents:UIControlEventTouchUpInside];
    checkButton.backgroundColor = [UIColor clearColor];
    cell.accessoryView = checkButton;
    
    And the method:
    Code:
    - (void)checkButtonTapped:(id)sender event:(id)event {
    	NSSet *touches = [event allTouches];
    	UITouch *touch = [touches anyObject];
    	CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    	NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
    	if (indexPath != nil)
    	{
    		if([[[array objectAtIndex:indexPath.row] objectAtIndex:1] isEqualToString:@"unchecked"]) {
    			NSLog(@"unchecked");
    			NSArray * theArray = [[NSArray alloc] initWithObjects:[[array objectAtIndex:indexPath.row] objectAtIndex:0], @"checked", nil];
    			[array removeObjectAtIndex:indexPath.row];
    			[array insertObject:theArray atIndex:indexPath.row];
    			[theArray release];
    		} else if([[[array objectAtIndex:indexPath.row] objectAtIndex:1] isEqualToString:@"checked"]) {
    			NSLog(@"checked");
    			NSArray * theArray = [[NSArray alloc] initWithObjects:[[array objectAtIndex:indexPath.row] objectAtIndex:0], @"unchecked", nil];
    			[array removeObjectAtIndex:indexPath.row];
    			[array insertObject:theArray atIndex:indexPath.row];
    			[theArray release];
    		}
    		[self.tableView reloadData];
    	}
    }
    
    
  2. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Why would it reload the image? There is nothing there telling it to reload/refresh/whatever the image.

    Go ahead and subclass your UITableViewCells. It doesn't hurt. Frankly, I wouldn't dream of using a non subclassed UITableViewCell.

    Example benefit of subclassing the UITableViewCell would be the ability to cache the images within the cell and not have to worry about reloading them EVERY SINGLE time the cell gets added to the table. It would make your code much faster.
  3. Steaps

    Steaps New Member

    Joined:
    Oct 24, 2007
    Messages:
    5,074
    Likes Received:
    41
    Device:
    iPod touch
    I have custom tableview cells, I was just making this project as a test.
    Shouldn't the cell reload when you call [self.tableView reloadData]; though? Because that's what i meant when i said no reloading. I call that method and it stays the same.
  4. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Are you specifically calling anything to reload the button? No. Therefore the button doesn't reload. Nor should it.
  5. Steaps

    Steaps New Member

    Joined:
    Oct 24, 2007
    Messages:
    5,074
    Likes Received:
    41
    Device:
    iPod touch
    But it's recreating the button.
    It reloads when it's the accessoryView, but not when it's a subview of the contentView.
  6. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    That's because accessoryView has built in commands within the UITableViewCell that handle that case. The same thing you will need to do in your UITableViewCell subclass.

    Also, the cell isn't recreating the button each time, YOU are in your cellForRow method. ( UIButton * checkButton = [UIButton buttonWithType:UIButtonTypeCustom]; )

    Every time you load a new cell, you create a new button, which is horrible fail. Adding that button in with a subclass of UITableViewCell would be the best way to only have ONE button that is very easily managed in the cell's own code. Just create a new protocol with a leftButtonClickedForRow, similar to the accessoryButtonTappedforRow, and have your tableViewController handle that.

    Alternatively, create that button as a property of your cell and simply assign a target and action to it from your tableViewController. Either way works (I prefer the former).


    EDIT: I just realized, you're setting it as the accessory view? Why not set it as an accessory button, to replace the disclosure button?
  7. Steaps

    Steaps New Member

    Joined:
    Oct 24, 2007
    Messages:
    5,074
    Likes Received:
    41
    Device:
    iPod touch
    I don't want it as an accessoryView or accessoryButton. I want it on the left side of the cell.

Share This Page