Odd UITableView Behavior - iphone

Please take a look at the image.
I have a UITableView with custom cells and 2 sections. Once the UITableView populates enough cells that they all can't be shown on the screen, the last cell in the last section appears at the very top of the screen. The cell shouldn't even be visible in the UITableView since it's the last cell, and it is appearing completely outside the UITableView, at the top of the screen. I'm at a loss for even knowing where to begin to look in my code for this issue. I've only created a couple of UITableViews so I'm definitely not an expert on all the potential causes for this bug. The Table is set up through IB and the initialization code is in viewWillAppear, although there isn't much set up code. I am currently reading up on UITableView's scrollView, along with contentInset to see if there might be an explanation for this behavior. Has anyone encountered such a bug? I feel like it's unique enough that it may not be necessary to comb through all my code to determine. Regardless, I will post the relevant code below. Thank you for your help!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *uniqueIdentifierForPlayerCell = #"customPlayerCell";
//Initialize PlayerTableViewCell and set it's properties
PlayerTableViewCell *playerCell = nil;
playerCell = (PlayerTableViewCell *)[tableView dequeueReusableCellWithIdentifier:uniqueIdentifierForPlayerCell];
if (playerCell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PlayerTableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[PlayerTableViewCell class]]) {
playerCell = (PlayerTableViewCell *)currentObject;
break;
}
}
}
playerCell.textLabel.opaque = NO;
playerCell.textLabel.textColor = self.textColor;
playerCell.textLabel.font = [UIFont systemFontOfSize:18.0];
playerCell.textLabel.backgroundColor = [UIColor clearColor];
playerCell.selectionStyle = UITableViewCellSelectionStyleNone;
playerCell.accessoryButton.hidden = YES;
playerCell.reorderButton.hidden = YES;
NSString *uniqueIdentifierForAlleyCell = #"customAlleyCell";
//Initialize AlleyTableViewcell and set it's properties
AlleyTableViewCell *alleyCell = nil;
alleyCell = (AlleyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:uniqueIdentifierForAlleyCell];
if (alleyCell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"AlleyTableViewCell" owner:nil options:nil];
for(id currentObject in topLevelObjects) {
if([currentObject isKindOfClass:[AlleyTableViewCell class]]) {
alleyCell = (AlleyTableViewCell *)currentObject;
break;
}
}
}
alleyCell.textLabel.opaque = NO;
alleyCell.textLabel.textColor = self.textColor;
alleyCell.textLabel.font = [UIFont systemFontOfSize:18.0];
alleyCell.textLabel.backgroundColor = [UIColor clearColor];
alleyCell.selectionStyle = UITableViewCellSelectionStyleNone;
alleyCell.accessoryButton.hidden = YES;
alleyCell.deleteButton.hidden = YES;
//Alternate background colors for each section where section 0 is Alley section and section 1 is Player section. Stores the RGB values of the specific background color to the specific cell for future use
if(indexPath.section == 0 && (indexPath.row %2 == 0)) {
alleyCell.contentView.backgroundColor = self.backgroundColor;
alleyCell.isRed = 95.0/255.0;
alleyCell.isGreen = 94.0/255.0;
alleyCell.isBlue = 94.0/255.0;
self.alleyField.backgroundColor = self.backgroundColor;
}
else if(indexPath.section == 0 && (indexPath.row %2 == 1)){
alleyCell.contentView.backgroundColor = self.alternateColor;
alleyCell.isRed = 92.0/255.0;
alleyCell.isGreen = 92.0/255.0;
alleyCell.isBlue = 92.0/255.0;
self.alleyField.backgroundColor = self.alternateColor;
}
else if(indexPath.section == 1 && (indexPath.row %2 == 0)) {
playerCell.contentView.backgroundColor = self.backgroundColor;
playerCell.isRed = 95.0/255.0;
playerCell.isGreen = 94.0/255.0;
playerCell.isBlue = 94.0/255.0;
self.playerField.backgroundColor = self.backgroundColor;
}
else if(indexPath.section == 1 && (indexPath.row %2 == 1)) {
playerCell.contentView.backgroundColor = self.alternateColor;
playerCell.isRed = 92.0/255.0;
playerCell.isGreen = 92.0/255.0;
playerCell.isBlue = 92.0/255.0;
self.playerField.backgroundColor = self.alternateColor;
}
//If Alley array is empty, add alley TextField and return cell
if(indexPath.section == 0) {
if([self.allAlleys count] == 0) {
[alleyCell addSubview:self.alleyField];
self.alleyField.text = nil;
return alleyCell;
}
//Else set the alley name to the nameLabel text and return cell
else {
if(indexPath.row < [self.allAlleys count]) {
alleyCell.textLabel.text = [self.allAlleys objectAtIndex:indexPath.row];
if([alleyCell.textLabel.text isEqualToString: self.selectedAlley]) {
alleyCell.accessoryButton.hidden = NO;
}
else {
alleyCell.accessoryButton.hidden = YES;
}
return alleyCell;
}
//Add alley TextField to the last cell of the UITableView and return cell
else {
[alleyCell addSubview:self.alleyField];
self.alleyField.text = nil;
return alleyCell;
}
}
}
//If Player array is empty, add Player TextField and return cell
else if(indexPath.section == 1) {
if([self.bowlrNames count] == 0) {
[playerCell addSubview:self.playerField];
self.playerField.text = nil;
return playerCell;
}
//Else set the Player name to the nameLabel text and return cell
else {
if(indexPath.row < [self.bowlrNames count]) {
playerCell.textLabel.text = [self.bowlrNames objectAtIndex:indexPath.row];
for(int i = 0; i < [self.selectedBowlrs count]; i++) {
if([playerCell.textLabel.text isEqualToString: [self.selectedBowlrs objectAtIndex:i]]) {
playerCell.accessoryButton.hidden = NO;
playerCell.reorderButton.hidden = NO;
}
}
return playerCell;
}
//Add Player textField to the last cell of the UITableView and return cell
else {
[playerCell addSubview:self.playerField];
self.playerField.text = nil;
return playerCell;
}
}
}
}
//Actions for selecting a row in the UITable
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//If it is in the Alley section
if(indexPath.section == 0) {
//If the selected cell is the same as the last selected cell
if(self.lastIndexPathForAlleyCells && indexPath.row == self.lastIndexPathForAlleyCells.row) {
[tableView beginUpdates];
self.lastIndexPathForAlleyCells = nil;
AlleyTableViewCell *previousCell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
//[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
previousCell.selected = NO;
self.selectedAlley = nil;
previousCell.accessoryButton.hidden = YES;
[tableView endUpdates];
return;
}
//Else the selected cell is not the last selected cell
AlleyTableViewCell *previousCell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:self.lastIndexPathForAlleyCells];
previousCell.selected = NO;
previousCell.accessoryButton.hidden = YES;
AlleyTableViewCell *cell = (AlleyTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.selected = YES;
cell.accessoryButton.hidden = NO;
self.selectedAlley = cell.textLabel.text;
self.lastIndexPathForAlleyCells = indexPath;
[self.tableView reloadData];
}
else if(indexPath.section == 1) {
PlayerTableViewCell *cell = (PlayerTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
//If player is not already selected
if([self playerIsSelected:cell.textLabel.text] == NO) {
//Set selected to YES and reveal buttons
cell.selected = YES;
cell.accessoryButton.hidden = NO;
cell.reorderButton.hidden = NO;
//If 8 Players are currently selected, UIAlertView informs user they have reached the limit
if([self.selectedBowlrs count] == 8) {
NSString *message = #"You can only select up to 8 players";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Max Players Selected" message:message delegate:self cancelButtonTitle:[self okButtonTitle] otherButtonTitles:nil, nil];
alertView.tag = TAG_FULLGAME;
[alertView show];
}
else {
//Insert name into selectedBowlrs array
[self.selectedBowlrs insertObject:cell.textLabel.text atIndex:0];
//Reorder bowlrNames array
NSString *bowlrName = [self.bowlrNames objectAtIndex:indexPath.row];
[self.bowlrNames removeObjectAtIndex:indexPath.row];
[self.bowlrNames insertObject:bowlrName atIndex:0];
//Move selected row to top of section
[self moveIndexPathToTop:indexPath];
}
}
//Else the player is already selected
else {
//Set selected to NO and hide buttons
cell.selected = NO;
cell.accessoryButton.hidden = YES;
cell.reorderButton.hidden = YES;
[self.selectedBowlrs removeObject:cell.textLabel.text];
[self.bowlrNames removeObject:cell.textLabel.text];
[self.bowlrNames insertObject:cell.textLabel.text atIndex:[self.selectedBowlrs count]];
[self moveIndexPathToMiddle:indexPath];
for(int i = 0; i < [self.selectedBowlrs count]; i++) {
NSLog(#"%#", [self.selectedBowlrs objectAtIndex:i]);
}
}
}
[self performSelector:#selector(reloadData) withObject:nil afterDelay:.25];
}
//Returns the number of rows for each section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
//For Alley section
case 0:
//If the array is empty, return 1 row for the Alley Textfield
if([self.allAlleys count] == 0)
return 1;
//Else return the number of elements in the array + 1 for the Alley Textfield
else
return [self.allAlleys count] + 1;
break;
//For Player section
case 1:{
//If the array is empty, return 1 row for the Player Textfield
if([self.bowlrNames count] == 0)
return 1;
//Else return the number of elements in the array + 1 for the Player Textfield
else
return [self.bowlrNames count] + 1;
break;
}
default:
break;
}
return 0;
}
//Set up appearance for section headers
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.tableView.bounds.size.width, 25.0)];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
CGFloat isRed = 84.0/255.0;
CGFloat isGreen = 84.0/255.0;
CGFloat isBlue = 84.0/255.0;
self.headerColor = [[UIColor alloc]initWithRed:isRed green:isGreen blue:isBlue alpha:0.5];
headerLabel.backgroundColor = self.headerColor;
headerLabel.opaque = NO;
headerLabel.textColor = self.textColor;
headerLabel.highlightedTextColor = [UIColor whiteColor];
headerLabel.font = [UIFont systemFontOfSize:18.0];
headerLabel.frame = CGRectMake(0.0, 0.0, self.tableView.bounds.size.width, 25.0);
if (section == 0) {
[headerView setBackgroundColor:self.backgroundColor];
headerLabel.text = #"Alley";
[headerView addSubview:headerLabel];
}
else {
[headerView setBackgroundColor:self.backgroundColor];
headerLabel.text = #"Bowlr";
[headerView addSubview:headerLabel];
}
return headerView;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
//Used to delete row of UITable
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
self.indexPathForEditing = indexPath;
if(editingStyle == UITableViewCellEditingStyleDelete) {
//For Alley section
if(indexPath.section == 0) {
//Set up UIAlertView
NSString *message = #"Are you sure?";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Delete Alley?" message:message delegate:self cancelButtonTitle:[self cancelButtonTitle] otherButtonTitles:[self deleteButtonTitle], nil];
alertView.tag = TAG_Alley;
[alertView show];
}
//For Player section
else if(indexPath.section == 1) {
//Set up UIAlertView
NSString *message = #"All information for this Bowlr will be deleted";
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Delete Bowlr?" message:message delegate:self cancelButtonTitle:[self cancelButtonTitle] otherButtonTitles:[self deleteButtonTitle], nil];
alertView.tag = TAG_Player;
[alertView show];
}
}
[self performSelector:#selector(reloadData) withObject:nil afterDelay:.25];
}

Okay, I think there's two basic things you need to remember here.
(1) You must never add something to the cell as a subview. Add it only to the cell's contentView. This code is wrong: [alleyCell addSubview:self.alleyField];
(2) These cells are being reused. You may have 100 rows but only 10 cells, being constantly reused as the user scrolls. Therefore you must completely set up every cell from an empty state, and if it isn't in the empty state to start with, you need to get it into the empty state. If you add a textfield to a cell in one pass thru cellForRowAtIndexPath, you must remember to remove the textfield in every other pass thru cellForRowAtIndexPath, or the textfield can show up in other rows because another row might reuse that same cell.
(See also the discussion towards the end of this section of my book: http://www.apeth.com/iOSBook/ch21.html#_the_three_big_questions It discusses a simple consequence of forgetting that the cells are reused.)
Also, I need hardly add that frame matters. You are adding a subview, but I have no idea what its frame is. With the right (meaning wrong) frame value, that subview could appear outside the cell. Also, are you using cells of different heights? If so, remember that because the cell is being reused, its height can change. Thus, autoresizing behavior can cause the frame to change.

Related

Sections Expansion in UITableview - When pushed again to the view the expanded section gets disappear

Trying to expand the sections in UITableview. Everything is working fine but if the expanded section is not closed and the view is popup and then push to that view again where tableview is, the section expanded last time gets disappear and if any section in tableview selected the app crashes. I checked through breakpoint the issue is next time it starts with section1 not from section0. Why this is happening i am not getting. Below is the code i am using.
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.arrList count];
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section == 0)
{
if(indexSectionOne)
{
return [self.arrProductsList count];
}
else
{
return 1;
}
}
if(section == 1)
{
if(indexSectionTwo)
{
return [self.arrServicesList count];
}
else
{
return 1;
}
}
else
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"CellIdentifier";
AboutCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell==nil)
{
cell = [[AboutCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}
/*
if((indexPath.section == 0)||(indexPath.section == 1))
{
if(indexPath.row == 0)
{
cell.imgDwnView.image = [UIImage imageNamed:#"down_arrow_about_iPhone.png"];
}
}
*/
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
if(indexPath.section == 0)
{
if(indexPath.row == 0)
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.imgDwnView.image = [UIImage imageNamed:#"down_arrow_about_iPhone.png"];
}
//if(indexPath.row != 0)
else
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.imgView.image = [UIImage imageNamed:[self.arrImages objectAtIndex:0]];
cell.lblView.text = [[self.arrProductsList objectAtIndex:indexPath.row-1] valueForKey:#"ProductName"];
cell.txtView.text = [[self.arrProductsList objectAtIndex:indexPath.row-1] valueForKey:#"ProductDescription"];
}
}
if(indexPath.section == 1)
{
if(indexPath.row == 0)
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.imgDwnView.image = [UIImage imageNamed:#"down_arrow_about_iPhone.png"];
}
//if(indexPath.row != 0)
else
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.imgView.image = [UIImage imageNamed:[self.arrImages objectAtIndex:1]];
cell.lblView.text = [[self.arrServicesList objectAtIndex:indexPath.row-1] valueForKey:#"LinkTitle"];
cell.txtView.text = [[self.arrServicesList objectAtIndex:indexPath.row-1] valueForKey:#"ProductDescription"];
}
}
if(indexPath.row == 0)
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"cell_background_about_iPhone.png"]];
cell.lblView.text = [self.arrList objectAtIndex:indexPath.section];
cell.imgView.image = [UIImage imageNamed:[self.arrImages objectAtIndex:indexPath.section]];
cell.lblView.font = [UIFont fontWithName:#"NeoSansCyr-Regular" size:15.0f];
cell.lblView.textColor = [UIColor colorWithRed:144.0/255.0 green:8.0/255.0 blue:8.0/255.0 alpha:1.0];
}
else
{
NSLog(#"row:%d section:%d", indexPath.row, indexPath.section);
cell.lblView.frame = CGRectMake(60, 15, 150, 25);
cell.imgView.frame = CGRectMake(13, 15, 30, 30);
cell.txtView.frame = CGRectMake(60, 42, 180, 50);
cell.imgDwnView.frame = CGRectMake(270, 18, 19, 10);
cell.imgDwnView.image = [UIImage imageNamed:#"down_arrow_about_iPhone.png"];
//cell.lblView.text = #"Labels";
// cell.imgView.image = [UIImage imageNamed:#"Icon-small.jpg"];
// cell.txtView.text = #"Description";
cell.contentView.backgroundColor = [UIColor whiteColor];
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section == 0)
{
indexSectionOne = !indexSectionOne;
if(indexSectionOne)
{
}
else
{
}
[self.tblAboutView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
if(indexPath.section == 1)
{
indexSectionTwo = !indexSectionTwo;
if(indexSectionTwo)
{
}
else
{
}
[self.tblAboutView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
if(indexPath.section == 2)
{
MapViewController *mapView = [[MapViewController alloc]initWithNibName:#"MapViewController" bundle:nil];
mapView.strTitle = #"Branches/ATM";
[self.navigationController pushViewController:mapView animated:YES];
}
if(indexPath.section == 3)
{
MapViewController *mapView = [[MapViewController alloc]initWithNibName:#"MapViewController" bundle:nil];
mapView.strTitle = #"Sadara Centre";
[self.navigationController pushViewController:mapView animated:YES];
}
if(indexPath.section == 4)
{
NSString *strRoadAsstNo = [dictData valueForKey:#"RoadSideAssistanceNo"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:strRoadAsstNo]];
}
if(indexPath.section == 5)
{
NSString *strContactNo = [dictData valueForKey:#"ContactCenterNo"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:strContactNo]];
}
}
Update:
Error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (33) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Thanks in advance. Please guide for above where i am doing wrong.

cell order change while tableview scrolls up and down

I am doing one registration form for iphone application. In that am having one tableview with four section.In last section am having one row with register button.I got the tableview with data well.But while scrolling the tableview up and down my register button goes to 2nd section.I added the code below.What wrong i did in this.Help me to solve.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
// static NSString *CellIdentifier = #"Cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSString *identifier = #"reuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
NSLog(#" row and section ===== %d,%d",indexPath.row,indexPath.section);
if(indexPath.section != 3)
{
UILabel *lbl_title = [[UILabel alloc] initWithFrame:(isiPad?CGRectMake(7,10,250,50):CGRectMake(70,40,340, 35))];
[lbl_title setFont:[UIFont fontWithName:#"Verdana-Bold" size:(isiPad?20:13)]];
lbl_title.backgroundColor = [UIColor clearColor];
[lbl_title setTextColor:[UIColor blackColor]];
lbl_title.tag = ((indexPath.section+1)*10)+indexPath.row;
//NSLog(#"lbl data tag %d",lbl_title.tag);
lbl_title.textAlignment = UITextAlignmentLeft;
[cell.contentView addSubview:lbl_title];
UILabel *lbl_data = [[UILabel alloc] initWithFrame:(isiPad?CGRectMake(260,10,410,50):CGRectMake(70,40,340, 35))];
[lbl_data setFont:[UIFont fontWithName:#"Verdana-Bold" size:(isiPad?20:13)]];
lbl_data.backgroundColor = [UIColor clearColor];//25-25-112
[lbl_data setTextColor:[UIColor colorWithRed:25.0/255.0 green:25.0/255.0 blue:112.0/255.0 alpha:1.0]];
lbl_data.textAlignment = UITextAlignmentCenter;
lbl_data.tag = ((indexPath.section+1)*100)+indexPath.row;
//NSLog(#"lbl data tag %d,%#",lbl_data.tag,lbl_data);
[cell.contentView addSubview:lbl_data];
if(indexPath.section == 0)
{
if(indexPath.row == 0)
{
lbl_title.text = #"Email";
}
else if(indexPath.row == 1)
{
lbl_title.text = #"Password";
}
else if(indexPath.row == 2)
{
lbl_title.text = #"Confirm password";
}
}
else if(indexPath.section == 1)
{
if(indexPath.row == 0)
{
lbl_title.text = #"First name";
}
else if(indexPath.row == 1)
{
lbl_title.text = #"Last name";
}
else if(indexPath.row == 2)
{
lbl_title.text = #"Nickname";
}
else if(indexPath.row == 3)
{
lbl_title.text = #"Gender";
}
}
else if(indexPath.section == 2)
{
if(indexPath.row == 0)
{
lbl_title.text = #"City";
}
else if(indexPath.row == 1)
{
lbl_title.text = #"State";
}
else if(indexPath.row == 2)
{
lbl_title.text = #"Country";
}
}
}
if(indexPath.section == 3)
{
if(indexPath.row == 0)
{
cell.backgroundColor = [UIColor colorWithRed:165.0/255.0 green:42.0/255.0 blue:42.0/255.0 alpha:1.0];//165-42-42
UIButton *btn_register = [[UIButton alloc] initWithFrame:isiPad?CGRectMake(10,0,660,70):CGRectMake(0,0,320,40)];
[btn_register addTarget:self action:#selector(btn_register_clicked:) forControlEvents:UIControlEventTouchUpInside];
[btn_register setTitle:#"Register" forState:UIControlStateNormal];
//btn_register.titleLabel.textAlignment = UITextAlignmentCenter;
btn_register.backgroundColor = [UIColor blueColor];
[btn_register setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn_register setFont:[UIFont fontWithName:#"Verdana-Bold" size:24]];
[cell.contentView addSubview:btn_register];
}
}
}
else
{
NSLog(#"updating cell.........");
}
return cell;
}
It gets repeated because you added it to a cell's contentview, and then you re-use that cell.
Rather than adding it in cell's contentView, add the button as a cell accessory.
cell.accessoryView = btn_register;
And in all other cells, set accessoryView to nil.
cell.accessoryView = nil;
Why don't you try setting different identifiers for each section of cells. You can also use Use [tableView dequeueReusableCellWithIdentifier:forIndexPath:
Using a different cell identifier for the "Register" cell should work. And your code will be much clear if you use a container to hold the data, like an NSDictionary. For example:
NSArray *account = #[#"Email", #"Password", #"Confirm password"];
NSArray *userInfo = #[#"First name", #"Last name", #"Gender", #"Nickname"];
// ...
NSDictionary *data = #{#"Account": account, #"User Information": userInfo /* ... */};

UIView appearing on multiple UITableViewCells

i have a little social network and i tried to implement the ratings code into the table view, it judges ratings with stars... the problem is that the second section displays ratings from the first table section
picture:
so you can see it displays ratings in some of the tableview cells, just the last couple, why would it be doing this?
drawing code:
-(void)drawRect:(CGRect)rect
{
if(_shouldDrawRating)
{
self.desc_image.layer.cornerRadius = 8;
self.desc_image.clipsToBounds = YES;
_rating = [[UIStarRateView alloc]initWithFrame:CGRectMake(220,35,70,15)];
[_rating setMaxStars:5];
[_rating setFullImage:[UIImage imageNamed:#"StarFull.png"]];
[_rating setHalfImage:[UIImage imageNamed:#"StarHalf.png"]];
[_rating setEmptyImage:[UIImage imageNamed:#"StarEmpty.png"]];
[_rating setRate:_postRating];
[self addSubview:_rating];
}
}
cell rendering code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Regular_Cell *cell;
// Configure the cell...
if(indexPath.section == 0)
{
if(indexPath.row < NUMBER_OF_DYNAMIC_ROWS_RECENT)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"default"];
if(cell == nil)
{
cell = [[Regular_Cell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"default"];
}
NSDictionary *dict = self.recentArray[indexPath.row];
[cell setShouldDrawRating:YES];
[cell.title_label setText:dict[#"title"]];;
[cell.author_label setText:[NSString stringWithFormat:#"Author: %#",dict[#"author"]]];
[cell.views_label setText:[NSString stringWithFormat:#"Views: %#",dict[#"views"]]];
[cell setPoll_idFromString:[NSString stringWithFormat:#"%#",dict[#"id"]]];
//options for image view
cell.desc_image.contentMode = UIViewContentModeScaleAspectFill;
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",dict[#"imageURL"]]];
[cell.desc_image setImageURL:imageURL];
[cell setPostRating:indexPath.row+0.5];
}
else if(indexPath.row == NUMBER_OF_DYNAMIC_ROWS_RECENT)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"See More"];
if(cell == nil)
{
cell = [[Regular_Cell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"See More"];
}
}
else
{
cell = nil;
}
NSLog(#"%#",indexPath);
}
if(indexPath.section == 1)
{
if(indexPath.row < NUMBER_OF_DYNAMIC_ROWS_TOP)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"default"];
if(cell == nil)
{
cell = [[Regular_Cell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"default"];
}
NSDictionary *dict = self.topViewedArray[indexPath.row];
[cell.title_label setText:dict[#"title"]];
[cell.author_label setText:[NSString stringWithFormat:#"Author: %#",dict[#"author"]]];
[cell.views_label setText:[NSString stringWithFormat:#"Views: %#",dict[#"views"]]];
[cell setPoll_idFromString:[NSString stringWithFormat:#"%#",dict[#"id"]]];
//options for image view
cell.desc_image.contentMode = UIViewContentModeScaleAspectFill;
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:#"%#",dict[#"imageURL"]]];
[cell.desc_image setImageURL:imageURL];
}
else if(indexPath.row == NUMBER_OF_DYNAMIC_ROWS_TOP)
{
cell = [tableView dequeueReusableCellWithIdentifier:#"See More"];
if(cell == nil)
{
cell = [[Regular_Cell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"See More"];
}
}
else
{
cell = nil;
}
NSLog(#"%#",indexPath);
}
return cell;
}
In section 1 you have to set the boolean to NO,It doesnt have a proper value now in section 1.I think you miss this line.
[cell setShouldDrawRating:NO];
Not only in Section 1 where ever you create the cell it must be implemented,Otherwise can cause problem of inconsistency in drawing
Replace code for setting cell labels, images etc from tableView:cellForRowAtIndexPath: and paste it in tableView:willDisplayCell:forRowAtIndexPath:. And setShouldDrawRating: in each section, not only in section number 0.

Inserting row to the section in tableview dyanmically iphone

I am trying to insert row in the section. cell is a custom cell having textfield.
Below is the code snippet,
-(NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
NSLog(#"row in section::%i %i", section, sectionRows);
if(section == 0)
return 1;
else if(section == 1)
return 1;
else
return sectionRows;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell rows in section%i %i", indexPath.section, [tableView numberOfRowsInSection:indexPath.section]);
static NSString *MyIdentifier = #"MyIdentifier";
MyIdentifier = #"TableView";
UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 31)];
[backgroundView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bg_accordian.png"]]];
CustomMyMedCellView *customCell;
UIView *viewToHide;
if(indexPath.section == 0)
{
customCell = (CustomMyMedCellView *)[tableView dequeueReusableCellWithIdentifier: MyIdentifier];
if (customCell == nil)
{
NSLog(#"in Section 1::::::");
[[NSBundle mainBundle] loadNibNamed:#"CustomMyMedCellView" owner:self options:nil];
customCell = customMyMedCellView;
[customCell setTextFieldValue:#"Teva Generic Med" editable:NO];
viewToHide= (UIView *)[customCell.contentView viewWithTag:4];
viewToHide.hidden = YES;
}
}else if(indexPath.section == 1)
{
customCell = (CustomMyMedCellView *)[tableView dequeueReusableCellWithIdentifier: MyIdentifier];
if(indexPath.row == 0)
{
if (customCell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"CustomMyMedCellView" owner:self options:nil];
customCell = customMyMedCellView;
CGRect frame = customCell.textField.frame;
frame.origin.x = 30.0;
customCell.textField.frame = frame;
[customCell setTextFieldValue:#"Accutane Capsules" editable:NO];
viewToHide = (UIView *)[customCell.contentView viewWithTag:2];
viewToHide.hidden = YES;
}
}
}else
{
customCell = (CustomMyMedCellView *)[tableView dequeueReusableCellWithIdentifier: MyIdentifier];
NSLog(#"in Section 3%#", customCell);
if (customCell == nil)
{
NSLog(#"in Section 3 if");
[[NSBundle mainBundle] loadNibNamed:#"CustomMyMedCellView" owner:self options:nil];
customCell = customMyMedCellView;
customMyMedCellView.textField.delegate = self;
CGRect frame = customCell.textField.frame;
frame.origin.x = 30.0;
customCell.textField.frame = frame;
[customCell setTextFieldValue:#"" editable:YES];
viewToHide = (UIView *)[customCell.contentView viewWithTag:2];
viewToHide.hidden = YES;
viewToHide = (UIView *)[customCell.contentView viewWithTag:4];
viewToHide.hidden = YES;
viewToHide = (UIView *)[customCell.contentView viewWithTag:5];
viewToHide.hidden = YES;
viewToHide = (UIView *)[customCell.contentView viewWithTag:6];
viewToHide.hidden = YES;
customCell.tag = indexPath.row;
[self.myMedsTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:(sectionRows-1) inSection:2] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
}
if(!self.isEditClicked)
{
viewToHide = (UIView *)[customCell.contentView viewWithTag:1];
viewToHide.hidden = YES;
}else{
viewToHide = (UIView *)[customCell.contentView viewWithTag:1];
viewToHide.hidden = NO;
}
customCell.backgroundView = backgroundView;
return customCell;
}
on clicking button i want to add row to section 2, for that below is the code i have added,
- (void)addButtonClick:(id)sender {
UIButton *clickedButton = (UIButton *) sender;
if(clickedButton.tag == 2)
{
NSMutableArray *indexPathsToInsert = [[NSMutableArray alloc] init];
NSInteger rowsInSection = [self.myMedsTableView numberOfRowsInSection:2];
if(rowsInSection>0){
NSLog(#"%#", [[self.myMedsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowsInSection-1 inSection:2]] viewWithTag:rowsInSection-1 ]);
CustomMyMedCellView *uiView = (CustomMyMedCellView *)[[self.myMedsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowsInSection-1 inSection:2]] viewWithTag:rowsInSection-1 ];
// NSLog(#"%#", uiView.subviews);
// UITextField *textField = (UITextField *)[uiView viewWithTag:3];
if([uiView.textField .text length] > 0)
{
sectionRows+=1;
}
}else{
sectionRows=1;
}
NSLog(#"Sectipn rows::::%i", sectionRows);
for (NSInteger i = 0; i < sectionRows; i++) {
NSLog(#"Sectipn rows:::: inside for");
[indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:2]];
}
NSLog(#"%i",[indexPathsToInsert count]);
[self.myMedsTableView beginUpdates];
[self.myMedsTableView insertRowsAtIndexPaths:indexPathsToInsert withRowAnimation:UITableViewRowAnimationBottom];
[self.myMedsTableView endUpdates];
//[self.myMedsTableView reloadData];
}else{
Search *tableViewController = [[Search alloc] initWithNibName:#"Search" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:tableViewController animated:YES];
}
But i am getting below error,
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 2. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (2 inserted, 0 deleted).'
Please help me i am new to the iphone.
Thanks in Advance
This error occurs because there is inconsistency between the cells that are given through "cellForRowAtIndexPath" and the index paths you are trying to update. When updating your table with new cells, make sure that your "cellForRowAtIndexPath" can create a cell for these indexes and also make sure that the numberOfRowsInSection is also consistent with this information.

iPhone UITableViewController showing/hiding rows during execution

I'm trying to realize a UITableViewController with 7 sections. Each sections has a number of rows that could change by user events. For istance, in the first section I have a single row with a UISwitch: if the user activates the switch, 2 more rows appear in that section. The same for section 2. Ok for now....
In sections 3,4,5 I also have a single row (Value1 Cell, iPhone general settings like): by pressing on that cell, the sections shows on the 2nd row a UISegmented control with 3 segments. By pressing one of that segments, the user make his choice and the segmented control row disappears, the sections has a single row again with the value choosed as detailTextLabel.
Well, all these procedures are managed with a reloadSections method that reloads the sections in with the user is interacting. My code is below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [ tableView dequeueReusableCellWithIdentifier: CellIdentifier];
CellIdentifier = [ NSString stringWithFormat: #"%d:%d", [ indexPath indexAtPosition: 0 ], [ indexPath indexAtPosition:1 ]];
//cell = nil;
if(indexPath.section == 0 && [indexPath indexAtPosition: 1] == 0)
{
CellIdentifier = #"test";
}
if (cell == nil) {
cell = [ [ [ UITableViewCell alloc ] initWithFrame: CGRectZero reuseIdentifier: CellIdentifier] autorelease ];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
switch ([ indexPath indexAtPosition: 0]) {
case(0): {
switch([ indexPath indexAtPosition: 1]) {
case(0):
{
positionControl.tag = 0;
[positionControl addTarget:self action:#selector(toggleSwitch:) forControlEvents:UIControlEventValueChanged];
[ cell addSubview: positionControl ];
cell.textLabel.text = NSLocalizedString(#"Position",#"");
}
break;
case(1):
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = NSLocalizedString(#"Some Position",#"");
cell.detailTextLabel.text = NSLocalizedString(#"Last Known Position",#"");
}
break;
case(2):
{
cell.textLabel.text = NSLocalizedString(#"ReDo Position",#"");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
break;
}
}
break;
case(1): {
switch ([ indexPath indexAtPosition: 1 ]) {
case(0):
{
photoControl.tag = 1;
[photoControl addTarget:self action:#selector(toggleSwitch:) forControlEvents:UIControlEventValueChanged];
[ cell addSubview: photoControl ];
cell.textLabel.text = NSLocalizedString(#"photos",#"");
}
break;
case(1):
{
cell.textLabel.text = NSLocalizedString(#"Take photo",#"");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
break;
case(2):
{
cell.textLabel.text = NSLocalizedString(#"Select from Roll",#"");
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
break;
}
}
break;
case(2): {
switch ([ indexPath indexAtPosition: 1 ]) {
case(0):
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = NSLocalizedString(#"size",#"");
if (UISegmentedControlNoSegment != [dimensionSegmentedControl selectedSegmentIndex]) {
cell.detailTextLabel.text = [dimensionSegmentedControl titleForSegmentAtIndex:[dimensionSegmentedControl selectedSegmentIndex]];
}
else {
cell.detailTextLabel.text = NSLocalizedString(#"Select",#"");
}
}
break;
case(1):
{
[dimensionSegmentedControl addTarget:self action:#selector(onSegmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:dimensionSegmentedControl];
}
break;
}
}
break; ...
Then my Action for switches:
- (IBAction) toggleSwitch: (id) sender {
UISwitch *switchControl = (UISwitch *) sender;
NSUInteger tag = switchControl.tag;
NSIndexSet *sectionsToReload = [[NSIndexSet alloc] initWithIndex:tag];
[self.tableView reloadSections:sectionsToReload withRowAnimation:NO];
[sectionsToReload release];}
Action for segmentedcontrol
- (IBAction) onSegmentedControlChanged: (id) sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSUInteger tag = segmentedControl.tag;
NSIndexSet *sectionsToReload = [[NSIndexSet alloc] initWithIndex:tag];
segmentedControl.momentary = YES;
[self.tableView reloadSections:sectionsToReload withRowAnimation:NO];
segmentedControl.momentary = NO;
[sectionsToReload release];}
This is the didSelectRow
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch ([ indexPath indexAtPosition: 0]) {
case(2): {
switch([ indexPath indexAtPosition: 1]) {
case (0): {
if (UISegmentedControlNoSegment != [dimensionSegmentedControl selectedSegmentIndex]) {
dimensionSegmentedControl.selectedSegmentIndex = [dimensionSegmentedControl selectedSegmentIndex];
}
else {
dimensionSegmentedControl.selectedSegmentIndex = 0;
}
NSIndexSet *sectionsToReload = [[NSIndexSet alloc] initWithIndex:2];
//[self.tableView reloadData];
[self.tableView reloadSections:sectionsToReload withRowAnimation:NO];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[sectionsToReload release];
}
break;
}
}
break;
case(3): {
switch([ indexPath indexAtPosition: 1]) {
case (0): {
if (UISegmentedControlNoSegment != [patientsSegmentedControl selectedSegmentIndex]) {
patientsSegmentedControl.selectedSegmentIndex = [patientsSegmentedControl selectedSegmentIndex];
}
else {
patientsSegmentedControl.selectedSegmentIndex = 0;
}
NSIndexSet *sectionsToReload = [[NSIndexSet alloc] initWithIndex:3];
//[self.tableView reloadData];
[self.tableView reloadSections:sectionsToReload withRowAnimation:NO];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[sectionsToReload release];
}
break;
default:
break;
}
}
break;
case(4): {
switch([ indexPath indexAtPosition: 1]) {
case (0): {
if (UISegmentedControlNoSegment != [patientsStateSegmentedControl selectedSegmentIndex]) {
patientsStateSegmentedControl.selectedSegmentIndex = [patientsStateSegmentedControl selectedSegmentIndex];
}
else {
patientsStateSegmentedControl.selectedSegmentIndex = 0;
}
NSIndexSet *sectionsToReload = [[NSIndexSet alloc] initWithIndex:4];
//[self.tableView reloadData];
[self.tableView reloadSections:sectionsToReload withRowAnimation:NO];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[sectionsToReload release];
}
break;
}
}
break;
case(5): {
switch([ indexPath indexAtPosition: 1]) {
case (0):
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel://4030"]];
break;
case (1):
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"tel://4030"]];
break;
}
}
break;
default: break;
}}
And finally my numbersOfRowsInSections, probably the problems source:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case (0):
{
if (!positionControl.on) {
return 1;
break;
}
return 3;
}
break;
case (1):
{
if (!photoControl.on) {
return 1;
break;
}
return 3;
}
break;
case (2):
{
if (UISegmentedControlNoSegment == [dimensionSegmentedControl selectedSegmentIndex] || [dimensionSegmentedControl isMomentary]) {
return 1;
break;
}
return 2;
}
break;
case (3):
{
if (UISegmentedControlNoSegment == [patientsSegmentedControl selectedSegmentIndex] || [patientsSegmentedControl isMomentary]) {
return 1;
break;
}
return 2;
}
break;
case (4):
{
if (UISegmentedControlNoSegment == [patientsStateSegmentedControl selectedSegmentIndex] || [patientsStateSegmentedControl isMomentary]) {
return 1;
break;
}
return 2;
}
break;
case (5): {
return 2;
}
break;
case (6): {
return 1;
}
break;
}
return 0;}
Well, now you can see my code, I'll explain my problem. When I deal with UISwitches, the sections reload properly....rows appear and disappear in the first two sections like a charm. But, when I click on the cells from sections with segmented controls, the first time everything is ok, the cell shows the segmented control, the user makes his choice, the segmented control disappears and the single row shows the user choice in the detailTextLabel.But when I try to click on another row, the app crashes with this exception:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 3. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted).'
2010-07-16 13:09:04.595 Barcodes[40421:207] Stack: (
35943515,
2535093513,
36027451,
1928964,
4228395,
4172781,
278302,
4188742,
4171908,
1425834,
35728064,
35724360,
43226645,
43226842,
3915695,
86847,
86454
)
Difference between two sections is that ones with UISwitches show and hide rows by activating/deactivating the switch, others by selecting rows (didSelectRow....).
ANY HELP??
Thank you in advance.
my code is good if I simply add a flag (BOOL) saying is each segmented control must be visible or not. Setting on "YES" and "NO" these flags and checking their value everything works properly.