The situation: Building a 4 section, varying rows tableview, using a subclass of Tableview Cell in storyboard with dynamic prototypes. Everything is running fine until I added a UISwitch (just in 2 rows). They appear 'initially' at the correct indexPath, but after scrolling, they begin appearing where they aren't supposed to be.
I've tried many different ideas, all of which change nothing... reuse identifiers & [cell.comboLabel addSubview:nil] in the 'non switch' rows.
Here's where I am.
(The 2 connected cell textFields are: nameLabel & comboLabel)
Code:
NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
NSString *value = [[a objectAtIndex:0] valueForKey:key];
static NSString *CellIdentifier = @"MasterCell";
UsersTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil)
{
// Do anything that should be the same on EACH cell here. Fonts, colors, etc.
// ** This is not being logged, ever **
NSLog(@" (%@,%@) Cell = nil", [indexPath section], [indexPath row] );
}
// Do anything that COULD be different on each cell here. Text, images, etc.
// Set the Item
cell.nameLabel.text = [NSString stringWithFormat:@"%@", key];
... other cell configuration
// Put On/Off switch in Password 'On' fields
if ([key isEqualToString:@"On"])
{
UISwitch *aSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(152, 4, 0, 0)];
if (!value)
[aSwitch setOn:YES animated:NO];
else
[aSwitch setOn:NO animated:NO];
[aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.comboLabel.text = nil;
cell.comboLabel.clipsToBounds = NO;
[cell.comboLabel addSubview:aSwitch];
}
else
{
cell.comboLabel.text = [NSString stringWithFormat: @"%@",value];
}
The situation: Building a 4 section, varying rows tableview, using a subclass of Tableview Cell in storyboard with dynamic prototypes. Everything is running fine until I added a UISwitch (just in 2 rows). They appear 'initially' at the correct indexPath, but after scrolling, they begin appearing where they aren't supposed to be.
I've tried many different ideas, all of which change nothing... reuse identifiers & [cell.comboLabel addSubview:nil] in the 'non switch' rows.
Here's where I am.
(The 2 connected cell textFields are: nameLabel & comboLabel)
Code:
NSArray *a = [[userDetailData objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
NSString *key = [[[a objectAtIndex:0] allKeys] objectAtIndex:0];
NSString *value = [[a objectAtIndex:0] valueForKey:key];
static NSString *CellIdentifier = @"MasterCell";
UsersTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil)
{
// Do anything that should be the same on EACH cell here. Fonts, colors, etc.
// ** This is not being logged, ever **
NSLog(@" (%@,%@) Cell = nil", [indexPath section], [indexPath row] );
}
// Do anything that COULD be different on each cell here. Text, images, etc.
// Set the Item
cell.nameLabel.text = [NSString stringWithFormat:@"%@", key];
... other cell configuration
// Put On/Off switch in Password 'On' fields
if ([key isEqualToString:@"On"])
{
UISwitch *aSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(152, 4, 0, 0)];
if (!value)
[aSwitch setOn:YES animated:NO];
else
[aSwitch setOn:NO animated:NO];
[aSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.comboLabel.text = nil;
cell.comboLabel.clipsToBounds = NO;
[cell.comboLabel addSubview:aSwitch];
}
else
{
cell.comboLabel.text = [NSString stringWithFormat: @"%@",value];
}
Any suggestions?
You should use a unique cell reuse identifier for cells that have a different structure. If you have a subset of your cells that have a segmented control in them, let's call those cells "segmentedCell". Ask for a "segmentedCell" when you try to dequeue a reused cell. Then, if no "segmentedCell" is available, create a cell using that identifier.
The idea is that you create cells of different types, and recycle them in that type. (You sort bottles, cans, and newspapers separately. If you need some newspaper to wrap fish, you ask for recycled newspaper. If you just ask for some recycled stuff, you might get a bottle instead, and you can't wrap up fish with a bottle.)
Once you have each type of cell being created and recycled in separate "recycling bins", you always get the correct type of cell, or are told there aren't any of that type.
Once you have a cell with the correct structure (layout of fields) you need to completely configure it, setting all values, including forcing fields to an empty/starting state if you don't use them.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
The idea is that you create cells of different types, and recycle them in that type. (You sort bottles, cans, and newspapers separately. If you need some newspaper to wrap fish, you ask for recycled newspaper. If you just ask for some recycled stuff, you might get a bottle instead, and you can't wrap up fish with a bottle.)
Are you suggesting that my code for the cell needs to be (almost) duplicated?
You are writing a factory that creates table view cells cells. It first looks for a recycled cell of the correct type. If it finds one, it sets all it's values and returns it. If it doesn't find it, it needs to build it.
It may be that you can make your code modular. IF all your cells have common elements, and the only difference for your cells that have a segmented control is the segmented control, then you could structure your code so the shared setup is only done once (in a separate method, maybe?)
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.