Reputation: 1509
I've UITableView
with dynamic cells and the cells are objects of custom UITableViewCell
subclass.
Each cell contains UILabel
,UIImageView
and UIButton
inside this UIImageView
. For clarity it is a music player which play's stream audio. My problem is saving pressed button state i.e for example when my UITableView
first loaded all buttons are in "deselected" state and each button has "play.png" as image, then if I press on this button its image changes to "pause.png" and target change too. It's very obvious, but if I will scroll up or down my UITableView
I'll see cells with "pause" button even if I never pressed on these buttons. I know that I must save cell button stae in NSMutableArray
and I already do it, but I guess that I do it wrong. Please help me solve this typical problem.
My source:
Play/pause switch method:
-(void)selectSettings:(AVMPlayButton *)sender{
CGPoint pointInTable = [sender convertPoint:sender.bounds.origin toView:musicTable];
NSIndexPath *indexPath = [musicTable indexPathForRowAtPoint:pointInTable];
AVMMusicCell *cell=(AVMMusicCell *)[musicTable cellForRowAtIndexPath:indexPath];
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
[sender setSelected:!sender.isSelected];
if (sender.isSelected) {
NSLog(@"SELECTED!");
if (![selectedButonsToPlay containsObject:[NSString stringWithFormat:@"%@",rowNsNum]] ) // HERE IS ARRAY WHICH CONTAINS SELECTED BUTTONS
{
[selectedButonsToPlay addObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
[sender addTarget:self action:@selector(pausePlay:) forControlEvents:UIControlEventTouchUpInside];
UIImage *pauseBackground = [UIImage imageNamed:@"pause.png"];
[sender setImage:pauseBackground forState:UIControlStateSelected];
}
}else {
NSLog(@"DESELECTED!");
if ( [selectedButonsToPlay containsObject:[NSString stringWithFormat:@"%@",rowNsNum]] )
{
[selectedButonsToPlay removeObject:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
// [cell.playButton addTarget:self action:@selector(startPlay:) forControlEvents:UIControlEventTouchUpInside];
NSLog(@"DEselected in didDEselect");
}
}
NSLog(@"you just select button");
}
-(IBAction)pausePlay:(AVMPlayButton*)sender{
AVMPlayButton *settings = (AVMPlayButton *)sender;
CGPoint pointInTable = [settings convertPoint:settings.bounds.origin toView:musicTable];
NSIndexPath *indexPath = [musicTable indexPathForRowAtPoint:pointInTable];
AVMMusicCell *cell=(AVMMusicCell *)[musicTable cellForRowAtIndexPath:indexPath];
UIImage *playBackground = [UIImage imageNamed:@"play.png"];
[cell.playButton setImage:playBackground forState:UIControlStateNormal];
[self pauseStream];
}
CellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"fileCell";
AVMMusicCell *cell = [self.musicTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[AVMMusicCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
AVMDataStore *oneItem = [musicArray objectAtIndex:indexPath.row];
oneItem = [musicArray objectAtIndex:indexPath.row];
[cell setMusic:oneItem];
cell.songName.text = oneItem.fileName;
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = MINT;
[cell setSelectedBackgroundView:bgColorView];
[cell.playButton addTarget:self action:@selector(selectSettings:) forControlEvents:UIControlEventTouchUpInside];
//save cell state for selected CELLS
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:(unsigned int)indexPath.row];
UIImage *pauseBackground = [UIImage imageNamed:@"pause.png"];
UIImage *playBackground = [UIImage imageNamed:@"play.png"];
if ([selectedButonsToPlay containsObject:[NSString stringWithFormat:@"%@",rowNsNum]] )
{
NSLog(@"cellforrow %lu contains selected buttons!",indexPath.row);
// NSLog(@"picture in cell %lu button is %@",indexPath.row,cell.playButton.imageView.image);
// [cell.playButton removeTarget:self action:@selector(selectSettings:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton addTarget:self action:@selector(pausePlay:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton setImage:pauseBackground forState:UIControlStateSelected];
}
else{
NSLog(@"cell %lu does not contain selected buton",indexPath.row);
[cell.playButton addTarget:self action:@selector(startPlay:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton setImage:playBackground forState:UIControlStateNormal];
}
return cell;
}
How it looks like:
When no one button is pressed:
Press play button and it's ok
Scroll down and see that on the fourth cell after "play" button is pressed too (but actually it's not)
Scroll up and see that selected button state moved on cell near "play" was really pressed
Upvotes: 2
Views: 1334
Reputation: 3812
You are very close. The issue is that the cell is reused and the state of the button will likely not be selected. Because the pause image only shows up when selected you just need to make sure the button is selected. You will also want to make sure it is unselected when needed. Hopefully that fixes the problem.
if ([selectedButonsToPlay containsObject:[NSString stringWithFormat:@"%@",rowNsNum]] )
{
NSLog(@"cellforrow %lu contains selected buttons!",indexPath.row);
// NSLog(@"picture in cell %lu button is %@",indexPath.row,cell.playButton.imageView.image);
// [cell.playButton removeTarget:self action:@selector(selectSettings:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton addTarget:self action:@selector(pausePlay:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton setImage:pauseBackground forState:UIControlStateSelected];
[cell.playButton setSelected:YES];
}
else{
NSLog(@"cell %lu does not contain selected buton",indexPath.row);
[cell.playButton addTarget:self action:@selector(startPlay:) forControlEvents:UIControlEventTouchUpInside];
[cell.playButton setImage:playBackground forState:UIControlStateNormal];
[cell.playButton setSelected:NO];
}
Upvotes: 4