swiftBoy
swiftBoy

Reputation: 35783

Why UITable rows get unchecked everytime when i scroll in iOS

I have designed a Table view , For Select Followers list to send message, so there I can select some followers and then send them message on twitter.

I am using UITable View with UITableViewCellAccessoryCheckmark to make this.

enter image description here

But when I scroll down table, the checked rows get unchecked every time.

I have decleard table view and an array for selected followers in FollowersListView.h

@interface FollowersListView : UIViewController<UITableViewDelegate,UITableViewDataSource>{

IBOutlet UITableView *tableFollowers;

NSMutableArray *listFollowrsName;   
NSMutableArray *listSelectedFollowrsId;
}

@property(nonatomic,retain) NSMutableArray *listFollowrsName;    
@property(nonatomic,retain) NSMutableArray *listSelectedFollowrsId;

@end

and my tableview code is like this in FollowersListView.m file

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return [listFollowrsName count];
}



- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"CellWithSwitch"];
    //if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithSwitch"] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:14];

    //cell.accessoryType = UITableViewCellAccessoryCheckmark;
    cell.accessoryType = UITableViewCellStyleDefault;
    //}

    NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;    

    return cell;
}

//to select a row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)path {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:path];


    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;        
        NSLog(@"row is un-checked %@",[NSNumber numberWithInt:path.row]);
        [listSelectedFollowrsId removeObject:[NSNumber numberWithInt:path.row]];
        NSLog(@"Now selected person are%@",listSelectedFollowrsId);

    } else {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        NSLog(@"row is checked %@",[NSNumber numberWithInt:path.row]);
        [listSelectedFollowrsId addObject:[NSNumber numberWithInt:path.row]];       
        NSLog(@"Now selected person are%@",listSelectedFollowrsId);
    }

}

I guess I need to load every cell as per the already stored selected list but not getting how to do.

Can anyone guide where I'm doing wrong, Any help would be appreciated

Edit

@Novarg

I have declared "listSelectedFollowrsId" as a NSMutable Array in .h file and initialized in viewDidLoad method then adding/removing values in didSelectRowAtIndexPath method to manage selected rows.

Upvotes: 1

Views: 2172

Answers (4)

M.B
M.B

Reputation: 885

you can use this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    
{       

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)

    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];        
        cell.backgroundColor=[UIColor clearColor];        
        cell.selectionStyle=UITableViewCellSelectionStyleNone;      
        cell.accessoryType=UITableViewCellAccessoryNone;            
    }
    else
    {
        UIView *subview;
        while ((subview= [[[cell  contentView]subviews]lastObject])!=nil)       
            [subview removeFromSuperview];            
    }

    NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
    cell.textLabel.text = cellValue;    
    return cell;
}

Upvotes: 1

Novarg
Novarg

Reputation: 7450

The thing is that you create a new cell every time that you scroll. The if (cell == nil) condition must be there, otherwise you will just keep on re-writing the cell over and over again.

Try the following:

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"CellWithSwitch"];
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellWithSwitch"] autorelease];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.textLabel.font = [UIFont systemFontOfSize:14];
    cell.accessoryType = UITableViewCellStyleDefault;
  }
  NSString *cellValue = [listFollowrsName objectAtIndex:indexPath.row];
  cell.textLabel.text = cellValue;    
  return cell;
}

It might not work, I'm using a windows machine right now, so can't compile the code and test it myself now.

Hope it helps

EDIT

If it doesn't solve the problem I'd also add a variable(probably an NSMutableDictionary) to keep a record of the names that have been "checked". Using that you can add the following just before return cell; in cellForRowAtIndexPath: method:

if ([[theDictionary objectForKey:/*your key here, can be anything*/]isEqualToString:/*string or whatever, just make sure that the checked ones are different from the unchecked ones*/])
  cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
  cell.accessoryType = UITableViewCellAccessoryNone;

EDIT 2

Here's what you should add right before return cell;(didn't see the listSelectedFollowrsId array before):

cell.accessoryType = UITableViewCellAccessoryNone;
for (int i = 0; i < [listSelectedFollowrsId count]; i++) {
  if ([[listSelectedFollowrsId objectAtIndex:i]intValue] == indexPath.row) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
  }
}

That will set the accessory to checkmark if the row has been previously tapped.

Upvotes: 5

andyroberts
andyroberts

Reputation: 3518

In cellForRowAtIndexPath you are always setting it to unchecked. You need to test whether that row is in the your list of selected followers, if so set the accessory accordingly.

This is all due to cell reuse to keep memory consumption low even for tables with thousands of rows.

Upvotes: 0

Apurv
Apurv

Reputation: 17186

Its because when you scroll the table, cellForRowAtIndexPath gets called.

In this function you are creating the cell again and again. So, your checkmarks are getting removed which you have marked in didSelectRowAtIndexPath.

Refer this link for detailed example of tableview.

Upvotes: 0

Related Questions