Ranga
Ranga

Reputation: 821

Issue on Scrolling the UITableView in iPhone.. data changes/ reloads when scrolls up/down

I have implemented a tableview with a custom cell.

1.Custom cell enter image description here

Custom cell having a label to display date and an UI Switch to set alarms.

My table view appears like like this when we switch on the uiswitches, enter image description here

2.Table view

When user scrolls down the table view the bottom switches are turned off

enter image description here

Same problem when scrolls up.

enter image description here

why this problem happens ? and how to prevent it?

Cell for row at index path method

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Note: I set the cell's Identifier property in Interface Builder to DemoTableViewCell.
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
    }

    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    //To display custom cell with label and switch
    if(indexPath.row< [appDelegate.alarmsArray count])
    {
        ReminderCell *cell = (ReminderCell *)[tableView dequeueReusableCellWithIdentifier:CellClassName];
        if (!cell)
        {
            NSArray *topLevelItems = [cellLoader instantiateWithOwner:self options:nil];
            cell = [topLevelItems objectAtIndex:0];
        }

        cell.reminderSwitch.tag = indexPath.row;

        NSMutableDictionary *dict = [appDelegate.alarmsArray objectAtIndex:indexPath.row];
        cell.label.text = [dict objectForKey:@"string"];
//=========================================
        cell.reminderSwitch.on = NO;
//=========================================
        return cell;
    }


    //Add + button on the last row of uitableview cell..
    if(indexPath.row == [appDelegate.alarmsArray count])
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeContactAdd];
        button.frame = CGRectMake(114, 9.5, 33, 33); 
        [button addTarget:self action:@selector(AddNewRow:) forControlEvents:UIControlEventTouchUpInside]; 
        [cell.contentView addSubview:button ];
        return cell;
    }

    return cell;
}

Upvotes: 1

Views: 1136

Answers (3)

Prakash
Prakash

Reputation: 872

In CustomCell Class Write function like this 

-(void)SetSwitchStatus:(NSInteger )stat
{
    if(stat == 0)
      //Set Switch off
    else
    //Set Switch on
} 


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    StoresCustomCell *cell =(StoresCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"StoresCustomCell" owner:self options:nil];
        cell = StoreCell;
    }
    [cell SetSwitchStatus:[StatusArr objectAtIndex:indexPath.row];
}

In ViewdidLoad Function Set 0 elements to all statusArr,,  StatusArr count = TableView rows Count

- (void)tableView:(UITableView *)sender didSelectRowAtIndexPath:(NSIndexPath *)path {

if([[StatusArr objectAtIndex:path.row] isEqualToString:@"0"])
   [StatusArr replaceObjectAtIndex:path.row withObject:@"1"]
else
   [StatusArr replaceObjectAtIndex:path.row withObject:@"0"]
}

Upvotes: 1

danh
danh

Reputation: 62676

The problem will be in the cellForRowAtIndexPath: datasource method. Remember that the cells are created and reused as the table scrolls, so the logic for each cell cannot make any assumptions about it's state.

You probably (you should) keep an array that has Alarms in it with time and a bool to indicate whether they are set...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"AlarmCell";  // your cell identifier goes here

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    CustomAlarmCell *alarmCell = (CustomAlarmCell *)cell;
    Alarm *alarm = [self.alarmArray objectAtIndex:indexPath.row];

    BOOL alarmIsSet = [alarm.isSet intValue];        // you should have an NSNumber 0 or 1 to indicate the alarm is set
    NSString *alarmTimeString = [alarm timeString];  // assume it has a date formatter and can render alarm time as string

    alarmCell.timeLabel.text = alarmTimeString;  
    alarmCell.isSetSwitch.on = alarmIsSet;

    return (UITableViewCell *)alarmCell;
}

Upvotes: 1

Most certanly you are not reusing the cells, then the switches are created each time a cell is displayed (and all the cell content too). But be careful, because although you reuse the cell views, you will need to set the switch on/off property according to the value you want. So your method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    {
        /** THIS SHOULD BE REPLACED BY YOUR CONSTRUCTOR FROM NIB FILE **/
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }

    UISwitch *switch = (UISwitch *)[cell viewWithTag:SWITCH_TAG];
    switch.on = *is_on*;

    return cell;
}

Upvotes: 1

Related Questions