I am writing a UITableView that contains 2 sections. When the table first loads all the cells are displaying the correct info, but when I start scrolling up and down, cells detailedTextLabel and accessoryType are being refreshed incorrectly, such that some cells that should only contain a detailedTextLabel also contain an accessory, and cells that should only contain an accessory also contain a detailedTextLabel.
Inside cellForRowAtIndexPath: I am using nested switch/case statements to apply the correct values to the cells in their respective section/row. As far as i can tell the logic in these statements is correct, so is it possible that the value of cell variable is inccorect when updating?
The table loads correctly but after scrolling accessoryType and detailedTextLabel gets mixed up.
Click for link to screen shots of the table.
Here is the code inside of my UITableViewController subclass:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionNames count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSArray *headingsSection = [cellTitles objectAtIndex:section];
return [headingsSection count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [sectionNames objectAtIndex:section];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
self.tableView.allowsSelection = YES;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[cellTitles objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
switch (indexPath.section) {
case 0:
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d%%", [[assistSettingsArray_glob objectAtIndex:indexPath.row] intValue]];
break;
case 1:
switch (indexPath.row) {
case 0:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
case 1:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
case 2:
if (defaultAssistOn) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
break;
}
break;
}
return cell;
}
Due to cell re-use, cells with previously set values re-appear.
Before the switch (indexPath.section) ..., initialize the detailTextLabel and accessoryType to defaults:
cell.detailTextLabel.text = #"";
cell.accessoryType = UITableViewCellAccessoryNone;
Try to enclose the code in each switch cases inside parantheisis. So the above code looks like this:
switch (indexPath.section) {
case 0: {
cell.detailTextLabel.text = [NSString stringWithFormat:#"%d%%",
[[assistSettingsArray_glob objectAtIndex:indexPath.row] intValue]];
break;
}
case 1: {
switch (indexPath.row) {
case 0: {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break; }
case 1: {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break; }
case 2: {
if (defaultAssistOn) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
break; }
default:
break;
}
break;
}
default:
break;
}
I am not sure whether this work. Do inform if it does :)
Related
following code sets cell texts and add a checkMark only to last selected. Always only one cell check marked and works properly excepting when it is displayed for first time. So, text is not showed for that cell (only that one) until you press any other cell. For example, if cellPos = 4 when viewDidLoad, that cell will not contain text.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString* cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
cell = (UITableViewCell*) [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryNone;
if (indexPath.section == 0) {
if(indexPath.row == cellPos)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.selected = YES;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selected = NO;
}
switch (indexPath.row) {
case 0:
cell.textLabel.text = #"English";
cell.imageView.image = [UIImage imageNamed:#"english.png"];
break;
case 1:
cell.textLabel.text = #"Español";
cell.imageView.image = [UIImage imageNamed:#"spanish.png"];
break;
case 2:
cell.textLabel.text = #"Deutsch";
cell.imageView.image = [UIImage imageNamed:#"germany.png"];
break;
case 3:
cell.textLabel.text = #"Français";
cell.imageView.image = [UIImage imageNamed:#"french.png"];
break;
case 4:
cell.textLabel.text = #"Italiano";
cell.imageView.image = [UIImage imageNamed:#"italian.png"];
break;
default:
break;}
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
cellPos = indexPath.row;
[tableView reloadData];
}
Have you tried moving the if-else block after the switch block? This way you set the text of the cell before you set the cell to selected. The fact that it only occurs the first time suggests to me that it may be an order of operations problem.
following code works properly but it applies same cell text to all sections. How could I apply selection case also depending on section? Thank you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
switch (indexPath.row) {
case 0:
cell.textLabel.text = #"English";
break;
case 1:
cell.textLabel.text = #"Chinese";
break;
case 2:
cell.textLabel.text = #"Japanese";
break;
default:
break;
}
return cell;
}
You can use indexPath.section to get the section number, just like how you're using indexPath.row for the row number.
You have to check for the indexPath.section and also indexPath.row:
if (indexPath.section == 0) {
if (indexPath.row) {
...
}
} else if (indexPath.section == 1)
if (indexPath.row) {
...
}
} else if ...
I have a table with 3 sections, all three sections have different number of rows. The cell values should populate from different array's.
So how should i find out which section is it in method cellForRowAtIndexPath:???
Please help!!!
Code:
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section
{
currentSection = section;
int number = 0;
switch (section) {
case 0:
number = self.basic.count;
break;
case 1:
number = allSectors.count;
break;
case 2:
number = 1;
break;
default:
number = 0;
break;
}
return number;
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]autorelease];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
CGFloat fontSize = [UIFont systemFontSize];
CGFloat smallFontSize = [UIFont smallSystemFontSize];
switch (indexPath.section) {
case 0:
cell.textLabel.text = [self.basic objectAtIndex:indexPath.row];
break;
case 1:
cell.textLabel.text = [self.allSectors objectAtIndex:indexPath.row];
break;
case 2:
cell.textLabel.text = #"None";
break;
default:
break;
}
return cell;
}
Just use indexPath.section to get the table section, and indexPath.row to get the row in that section. These properties are defined in the category NSIndexPath (UIKitAdditions).
I would like to get a TableView with different elements on the accessoryView, depending on the section. Everything works fine, but when I scroll down to section 2 and then scroll up again to section 0, the rows in section 0 have switchers. Could you please help me finding out what I'm doing wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger sectionIndex = [indexPath section];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *dictionary;
NSArray *array;
NSString *cellValue;
UISwitch *switchView;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
switch (sectionIndex) {
case 0:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
case 1:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
case 2:
switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
[switchView setOn:NO animated:NO];
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[switchView release];
break;
default:
break;
}
dictionary = [searchArray objectAtIndex:indexPath.section];
array = [dictionary objectForKey:#"advancedSearch"];
cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
You are dequeuing your table cells (cf. -[UITableView dequeueReusableCellWithIdentifier:]), which means that you are receiving table views that have already been allocated and possibly pre-populated with stale data. In case 0: and case 1: of your switch statement, you should add the following line:
cell.accessoryView = nil;
Use different cell identifiers for different cells.
Something like:
NSString *CellIdentifier;
switch ([indexPath row]) {
case 0: CellIdentifier = #"cell0";
break;
case 1: CellIdentifier = #"cell1";
break;
default: CellIdentifier = #"cell";
break;
}
Otherwise Xcode thinks that all your cells have the same look and tries to reuse them while you scroll.
The problem is from dequeueReusableCellWithIdentifier you must use different identifiers for different cells because you reuse them.
i am working on an iphone project that shows an artwork at the top tableview section (section 0) and shows a list of items in (section 1). the tableview looks like that:
section0:
ARTWORK IMAGE
section1:
cell1: text1
cell2: text2
.
.
. and so goe like that.
but strangely the program shows another imageview at the bottom of the page when i scroll down, but it shouldnt show that image because its not section 0.
heres the code for my program :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case 0:
return 1;
break;
case 1:
return [diskArray count];
break;
default:
return 0;
break;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0:
return 225;
break;
default:
return 44;
break;
}
}
// Customize the appearance of table view cells.
- (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...
if(indexPath.section == 0)
{
if(indexPath.row == 0)
{
NSLog(#"adding image to the cell");
UIImage *img = [UIImage imageNamed:#"artwork.jpeg"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(47, 0, 225, 225)];
imgView.image = img;
[cell addSubview:imgView];
[imgView release];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.text = nil;
}
}
else if(indexPath.section == 1){
cell.textLabel.text = [diskArray objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor darkGrayColor];
cell.textLabel.textColor = [UIColor whiteColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
The iPhone reuses old cells with the subview you've added. Try changing the CellIdentifier for each section.
It's because you reuse the cell, but nowhere it is reinitialized.
try this to remove the image :
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
} else {
[cell subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
//you should also reinit the other values, as textLabel, bgColor et al.
}