I have my uitableview with 20 rows which is showing a number of food items.
Each food item is having a check box along with it.
My problem is: If I check the first row of the check box and then scroll the tableview, the checkmark is reset.
How can I solve this problem? Please help me out.
Code update:
- (IBAction)buttonAction:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *checkboxButton = (UIButton*)sender;
checkboxButton.selected = !checkboxButton.selected;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:(UITableViewCell*)[[checkboxButton superview] superview]];
BOOL selected = [[selectedArray objectAtIndex:[indexPath row]] boolValue];
[selectedArray replaceObjectAtIndex:[indexPath row] withObject:[NSNumber numberWithBool:!selected]];
if (!self.checkedIndexPaths)
checkedIndexPaths = [[NSMutableSet alloc] init];
if(selected == NO)
{
NSLog(@"cvbcvbNO BOOL value"); // ...
// If we are checking this cell, we do
[self.checkedIndexPaths addObject:indexPath];
}
else
{
NSLog(@"cvbvbYES BOOL VALURE");
// If we are checking this cell, we do
[self.checkedIndexPaths removeObject:indexPath];
}
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Celhgl";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
profileName = [appDelegate.sentItemsList objectAtIndex:indexPath.row];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cb = [[UIButton alloc] initWithFrame:CGRectMake(5,10, unselectedImage.size.width, unselectedImage.size.height)];
[cb setImage:unselectedImage forState:UIControlStateNormal];
[cb setImage:selectedImage forState:UIControlStateSelected];
[cb addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
[cell.contentView addSubview:cb];
for (NSIndexPath *path in self.checkedIndexPaths)
{
NSLog(@"%d",path.row);
NSLog(@"%d",indexPath.row);
if (path.row == indexPath.row)
{
NSLog(@"df开发者_JAVA百科d %d",indexPath.row);
}
}
}
if ( tableView == myTableView )
{
titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 0, 150, 35)];
titleLabel.font = [UIFont boldSystemFontOfSize:13];
titleLabel.textColor = [UIColor blackColor];
[cell.contentView addSubview:titleLabel];
NSString *subjectData = [profileName.sent_subject stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
[titleLabel setText:[NSString stringWithFormat: @"%@ ", subjectData]];
}
return cell;
}
What's happening is that UITableView is recycling UITableViewCells to save memory. This means that as you scroll down the list the UITableView is taking cells off the top of the table and reusing them to display later items so when you scroll back up they have lost state.
You could rectify this by keeping an NSMutableSet
of checked indexPaths. When the user checks an item, you would add its indexPath
to this set. Then in your cellForRowAtIndexPath
you can make sure to check the item if it's in your set of checked items.
UPDATE
Here's a rough example of how this might work:
# MyTableView.h
@interface MyTableView: UITableView
<UITableViewDataSource, UITableViewDelegate>
{
NSMutableSet *checkedIndexPaths;
}
@property (nonatomic, retain) NSMutableSet *checkedIndexPaths;
@end
then
# MyTableView.m
#import "MyTableView.h"
@implementation MyTableView
@synthesize checkedIndexPaths;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Normal layout stuff goes here...
// ***Add code to make sure the checkbox in this cell is unticked.***
for (NSIndexPath *path in self.checkedIndexPaths)
{
if (path.section == indexPath.section && path.row == indexPath.row)
{
// ***We found a matching index path in our set of checked index paths, so we need to show this to the user by putting a tick in the check box, for instance***
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Normal stuff to handle visual checking/unchecking of row here
// Lazy-load the mutable set
if (!self.checkedIndexPaths)
checkedIndexPaths = [[NSMutableSet alloc] init];
// If we are checking this cell, we do
[self.checkedIndexPaths addObject:indexPath];
// If we are unchecking, just enumerate over the items in checkedIndexPaths and remove the one where the row and section match.
}
@end
This is all just skeleton code and isn't tested, but hopefully it gives you the jist.
save the checked items in your datasource.
I usually save the NSIndexPaths
of the selected objects in a NSMutableSet
.
And in tableView:cellForRowAtIndexPath:
I check if the indexpath is part of the set with the selected indexpaths.
@interface RootViewController : UITableViewController {
NSMutableSet *set;
}
// implementation:
- (void)viewDidLoad {
[super viewDidLoad];
set = [[NSMutableSet alloc] init];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
cell.textLabel.text = [NSString stringWithFormat:@"Cell %d", indexPath.row];
if ([set containsObject:indexPath]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([set containsObject:indexPath]) {
[set removeObject:indexPath];
}
else {
[set addObject:indexPath];
}
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
精彩评论