Reputation: 1253
This is a follow-up question to my previous one and this time I have a problem with UIButton that I have added in each UICollectionViewCell. Before diving into the problem, let me brief out all I've got so far.
Here's the basic rundown of how my UICollectionView in Scrolling Filmstrip style within UITableView works:
So far, I've been able to add UIButton in each UICollectionViewCell and when I tap the UIButton its image will change to checked mark but the problem occurs when I scroll up/down. Once the cell with checked mark UIButton is off-screen and scrolled back on-screen again, UIButton image starts to get messed around. For example, when UIButton image in cell1 should be checked mark but it's not. Instead checked mark will be appeared in another cell.
Here below is my relevant code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PostsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PostsCollectionViewCell" forIndexPath:indexPath];
NSDictionary *cellData = [self.collectionData objectAtIndex:[indexPath row]];
cell.postTextLabel.text = [cellData objectForKey:@"text"];
cell.locationNameLabel.text = [cellData objectForKey:@"locationName"];
// >>> Select Button <<<
UIButton *selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
[selectButton setFrame:CGRectMake(110, 150, 20, 20)];
[selectButton setImage:[UIImage imageNamed:@"uncheckedDot.png"] forState:UIControlStateNormal];
[selectButton setImage:[UIImage imageNamed:@"checkedDot.png"] forState:UIControlStateSelected];
[cell.contentView addSubview:selectButton];
[selectButton addTarget:self
action:@selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
// >>> End Select Button <<<<
return cell;
}
// >>> Select Button Method <<<
-(void) buttonPressed:(UIButton *)sender
{
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Any help would be greatly appreciated! Thanks in advance.
Upvotes: 1
Views: 388
Reputation: 2281
Maintain in your Data source which cell is to be selected by adding a key for each data source dict. For example:@"isSelected"
Then in cellForRowAtIndexPath:
if ([[cellData valueForKey:@"isSelected"] boolValue]) {
[selectButton setSelected:NO];
} else {
[selectButton setSelected:YES];
}
and in your -(void) buttonPressed:(UIButton *)sender
Method:
CGPoint point = [self.collectionView convertPoint:CGPointZero fromView:sender];
NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point];
NSDictionary *cellData = [self.collectionData objectAtIndex:[indexPath row]];
if ([[cellData valueForKey:@"isSelected"] boolValue]) {
[cellData setValue:@"false" forKey:@"isSelected"];
} else {
[cellData setValue:@"true" forKey:@"isSelected"];
}
[self.framesCollectionView reloadItemsAtIndexPaths:@[indexPath]];
AND
In your cellForRowAtIndexPath set a tag for the UIButton. Then before adding a UIButton as subview to the cell's contentView check if a view with this tag already exists. In case the cell has been reused, just use the already existing button.
Upvotes: 2
Reputation: 2107
Man, you should be aware that cells (both for UITableView and UICollectionView) are reused via the reuse deque under the hood of UIKit and are not obligated to keep their state consistent with regard to their position in a table view or a collection view. What you need to do is to make sure that the return value of dequeueReusableCellWithReuseIdentifier:
is then properly initialized (or, in your case, re-initialized) in accordance with the state of your data model. Basically, you need to store the state of your "checkmarks" (or "checkboxes", what have you) in an array or any other data structure. Then, when you call dequeueReusableCellWithReuseIdentifier:
, you should apply that stored state to the return value (the cell you're going to return for the collection view) you just got. Hope it's explained good enough. Good luck.
Upvotes: 2