UITextField in UITableViewCell - adding new cells - iphone

I am trying to create a table view similar to the YouTube video uploader view in the Photo Gallery on the iPhone.
Here's the basic setup.
I have a custom UITableViewCell created that contains a UITextField. Displaying the cell in my table works great and I can edit the text with no problems. I created an event hook so I can view when the text has changed in the text field.
[textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]
What I want to do is this. When the user first edits the text I want to insert a new cell into the table view below the current cell (newIndexPath is calculated prior to the proper position):
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
[self.tableView endUpdates];
Problem is when I run the cell insert code the cell is created but the text field's text updated briefly, but then the keyboard is dismissed and the text field is set back to an empty string.
Any help would be awesome! I've been banging my head about this one all day.
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
return 2;
else
return self.tags.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
cell = (SimpleTextFieldTableCell *)[tableView dequeueReusableCellWithIdentifier:tagCellIdentifier];
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"SimpleTextFieldTableCell" owner:nil options:nil] lastObject];
}
((SimpleTextFieldTableCell *)cell).textField.delegate = self;
((SimpleTextFieldTableCell *)cell).textField.tag = indexPath.row;
((SimpleTextFieldTableCell *)cell).textField.text = [self.tags objectAtIndex:indexPath.row];
[((SimpleTextFieldTableCell *)cell).textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
- (void)textFieldDidChange:(id)sender
{
UITextField *textField = sender;
[self.tags replaceObjectAtIndex:textField.tag withObject:textField.text];
if (textField.text.length == 1)
{
[textField setNeedsDisplay];
[self addTagsCell];
}
}
- (void)addTagsCell
{
NSString *newTag = #"";
[self.tags addObject:newTag];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:self.tags.count - 1 inSection:1];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationBottom];
[self.tableView endUpdates];
}

Only thing i can think of here is that perhaps when you insert a row the whole table view is reloaded, if you did not add your cell properly to the cell queue, they wont come back in the state that they were , therefore you are seeing empty cells as a result of the insert, just a guess, hope it helps.

Quick update:
Shouldn't matter but I notices you don't need:
[self.tableView beginUpdates]
[self.tableView endUpdates]
since you are performing one operation. Not sure if that matters (it shouldn't).
Update:
I should have said that such issues are pretty common. Here is a post related to your issue
http://www.bdunagan.com/2008/12/08/uitextview-in-a-uitableview-on-the-iphone/
Also, others have abstracted this out. Specifically I have tried this with no such issues:
http://furbo.org/2009/04/30/matt-gallagher-deserves-a-medal/
You could use:
http://github.com/joehewitt/three20/
But it has a bit of a learning curve.
Another Stackoverflow question tackling this issue:
Editing a UITextField inside a UITableViewCell fails
Excuse me not answering your issue directly, but I think that the solution might be contained in one of these links.
Original Answer:
Try:
[newTextField setNeedsDisplay];
Sometimes the tableviews can be "sticky" with updating UITextView/UITextField content.
If that doesn't work, be sure that you're backing model is also updated properly. You haven't displayed any code indicating you updated the model (although I assume you did, otherwise it would have likely thrown an exception).

Related

Unnatural jerk with UITableView whe cell height is changed dynamically

Here is what I want in my app. Shown below are two screenshots of the iPhone app Store:
I basically need a "Read More" feature just like it is used in the app store (See the "Description" section in the two images above). I am assuming that each section here (Description, What's New, Information etc.) is a table view cell. And the text inside is a UILabel or UITextField.
Here is what I have tried so far to add this feature:
NSString *initialText = #"Something which is not a complete text and created just as an example to...";
NSString *finalText = #"Something which is not a complete text and created just as an example to illustrate my problem here with tableviews and cel heights. bla bla bla";
NSInteger isReadMoreTapped = 0;
My cellForRowAtIndexPath function:
// Other cell initialisations
if(isReadMoreTapped==0)
cell.label.text = initialText;
else
cell.label.text = finalText;
return cell;
My heightForRowAtIndexPath function:
// Other cell heights determined dynamically
if(isReadMoreTapped==0){
cell.label.text = initialText;
cellHeight = //Some cell height x which is determined dynamically based on the font, width etc. of the label text
}
else{
cell.label.text = finalText;
cellHeight = //Some height greater than x determined dynamically
}
return cellHeight;
Finally my IBAction readMoreTapped method which is called when the More button is tapped:
isReadMoreTapped = 1;
[self.tableView beginUpdates];
[self.tableView endUpdates];
NSIndexPath* rowToReload = [NSIndexPath indexPathForRow:2 inSection:0]; // I need to reload only the third row, so not reloading the entire table but only the required one
NSArray* rowsToReload = [NSArray arrayWithObjects:rowToReload, nil];
[self.tableView reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationNone];
After doing all this, I do get the required functionality. The new height of that particular cell is calculated and the new text loaded into it. But there is a very unnatural jerk on the TableView which results in a bad User experience. That is not the case with the app store More button though. There is no unnatural jerk in its case. The TableView remains at its place, only the changed cell has its size increased with the text appearing smoothly.
How can I achieve the smoothness as done in the iPhone app store More button?
Your problem might come from reloading the row. You want to try to configure the cell properties directly. I usually use a dedicated method to configure my cell content so I don't have to reload rows.
- (void)configureCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if(isReadMoreTapped==0)
cell.label.text = initialText;
else
cell.label.text = finalText;
// all other cell configuration goes here
}
this method is called from the cellForRowAtIndexPath method and it will configure the cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[self configureCell:cell forRowAtIndexPath:indexPath];
return cell;
}
and you would call this method directly to avoid reloading:
isReadMoreTapped = 1;
[self.tableView beginUpdates];
[self.tableView endUpdates];
NSIndexPath* rowToReload = [NSIndexPath indexPathForRow:2 inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:rowToReload];
[self configureCell:cell forRowAtIndexPath:rowToReload];
Please try the following changes to your code, I think it will fix your problem.
no need to set cell.label.text in heightForRowAtIndexPath; Please remove them.
in the readMoreTapped, update table is enough:
isReadMoreTapped = 1;
[self.tableView beginUpdates];
[self.tableView endUpdates];
Either remove the calls to:
[self.tableView beginUpdates];
[self.tableView endUpdates];
Or change to ensure that your reloading code is between them. I would remove them as a single row reload is handled well with the method you use:
[self.tableView reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationNone];
You just need to specify a row animation like fade.
Okay, I finally solved the problem with the help of Matthias's answer (the accepted answer) and my own optimisations. One thing that definitely should be done is to create a dedicated function like configureCell: forRowAtIndexPath: to directly configure cell properties (see Mathias's answer). Everything remains the same with Matthias's answer except:
Before, I was calculating the heights of each cell everytime the heightForRowAtIndexPath function was called without caching(saving) them anywhere and hence when [self.tableView beginUpdates]; and [self.tableView endUpdates]; were called each cell height was calculated again. Instead, what you have to do is to save these cell heights in an array/dictionary so that whenever the More button is tapped, you calculate the height of only the cell that was changed. For the other cells, just query the array/dictionary and return the saved cell height. This should solve any problems with the tableView scroll after the cell height update. If anyone else still face a similar issue as this, please comment on this post. I would be happy to help

Change an image in a UITableViewCell without reloading cell

I'm writing an iPhone app with a UITableView as the primary user interface. Each section consists of two rows, a header and the body. When the user clicks on the header, I remove the second row by changing the numberOfRowsInSection value:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
cbwComponent *comp = [_componentController objectInListAtIndex:section];
if([comp hasContentsView] && !comp.contentsHidden){
return 2;
}else
return 1;
}
When the user selects the header, I'm using the following code:
comp.contentsHidden = YES;
[self.tableView beginUpdates];
NSArray *deleteIndexPaths = [[NSArray alloc] initWithObjects:[NSIndexPath indexPathForRow:1 inSection:indexPath.section], nil];
[self.tableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
It's working great, with a nice smooth fade effect. The problem is, I'm trying to add an indicator in the header cell (row 0) that changes when it's clicked on. To change that image I have to refresh the top row as well as the second row, which makes the transition look bad (well, not nearly as smooth). Is there a way to change the image in a UITableViewCell without refreshing the cell?
Thanks
EDIT: I figured it out! You can maintain the smooth transition as long as you reload that first row before you make the change to the second row. It has to be called inside of [tableView beginUpdates];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[[NSArray alloc] initWithObjects:[NSIndexPath indexPathForRow:0 inSection:indexPath.section], nil] withRowAnimation:UITableViewRowAnimationNone];
...
[self.tableView endUpdates];
Did the trick.
You could also subclass a tableview cell and implement a view transition in it that can be called from your view controller. You could then call that without having to reload the cell.
[(YourCustomCell*)[tableView cellForRowAtIndexPath:indexPathOfYourCell] fadeInIndicator];

Refreshing UITableview Section to One With Different Number of Rows

I've recently been working with a UITableView. It is dynamically populated once, then when a user selects an option, I want the list to change to a new one. I'm working with a grouped table with 3 sections and as you click on the rows the three groups need to be repopulated with a varying number of new rows. While my code works fine when there is the same number of rows in the new section as old, it crashes when that number changes. Interestingly though, it will wait to crash until it attempts to draw one of the cells that was there previously (the tableView still thinks the section has the old number of rows, tries to draw the cell that is no longer in my model object, and so I think it crashes because it's referencing a value in the new array that doesn't exist.
It crashes here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"MyCell"];
}
if (indexPath.section==2){
//CRASH BELOW
cell.textLabel.text = [NSString stringWithFormat:#"%#", (NSString *)[[[[storyArray objectAtIndex:pageNumber]getChoices] objectAtIndex:(unsigned long)indexPath.row]objectAtIndex:0]] ;
}
return cell;
}
The function I use to reload the table is here:
-(void)changePage:(int)pageChangeNumber{
NSLog(#"The page change! Changing to: %#",[[storyArray objectAtIndex:pageChangeNumber]getTitle]);
pageHeader.text=[[storyArray objectAtIndex:pageChangeNumber] getTitle];
pageBody.text=[[storyArray objectAtIndex:pageChangeNumber] getBody];
[myTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
[myTableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationFade];
[myTableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationFade];
[myTableView reloadData];
pageNumber=pageChangeNumber;
NSLog(#"Page Change Done");
}
I've also changed the numberofRowsInSection to be dynamic...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"Recounting Rows");
if (section==2){
return [[[storyArray objectAtIndex:pageNumber]getChoices] count];
} else {
return 0;
}
}
Any ideas on how I can get this working when the number of rows per section changes?
Thanks!
I don't know what crash you're getting, but I ran into crashes if the numberOfSectionsInTableView: or tableView:numberOfRowsInSection: methods returned different numbers of rows while the table was restructuring itself.
For example, UITableView calls those methods many times while it is redrawing (including during animations). In my backend, some of the values were changing during animation.
I had to take special care to synchronize those values before changing the UITableView
Before you update your table view's data and call reloadSections you need to first call [myTableView beginUpdates] and once you're done [myTableView endUpdates]

Expanding table view cells disappearing

I have cells that expand by changing their height with a setExpanded: method call.
I then call reloadRowsAtIndexPaths: to refresh the cells.
The problem is the cells simply disappear and randomly re-appear. I suspect this has to due with the way the indexing is working.
If I call reloadData or beginUpdates/endUpdates the cells work as expected, but I lose the animations.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
JVCell *cell = (JVCell*)[tableView cellForRowAtIndexPath:indexPath];
JVCell *previousCell = nil;
if( previousIndexPath_ != nil ) // set to nil in viewDidLoad
{
previousCell = (JVCell*)[tableView cellForRowAtIndexPath:previousIndexPath_];
}
// expand or collapse cell if it's the same one as last time
if( previousCell != nil && [previousIndexPath_ compare:indexPath] == NSOrderedSame && [previousCell expandable] )
{
[previousCell setExpanded:![cell expanded]];
NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
else
{
// collapse previous cell
if( previousCell != nil && [previousCell expandable] )
{
if( [previousCell expanded] ) [previousCell setExpanded:NO];
NSArray *indexPathArray = [NSArray arrayWithObject:previousIndexPath_];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
// expand new cell
if( [cell expandable] )
{
[cell setExpanded:YES];
NSArray *indexPathArray = [NSArray arrayWithObject:indexPath];
[tableView reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
previousIndexPath_ = indexPath;
// works as expected, but I lose the animations
//[tableView reloadData];
// works as expected, but I lose the animations
//[tableView beginUpdates];
//[tableView endUpdates];
}
EDIT: updated to include cellForRowAtIndexPath and heightForRowAtIndexPath methods:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
JVCellSectionData *sectionData = [sections_ objectAtIndex:section]; // NSArray of SectionData objects
NSArray *cellArray = [sectionData cells]; // NSArray of cells
UITableViewCell *cell = [cellArray objectAtIndex:row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
JVCellSectionData *sectionData = [sections_ objectAtIndex:section];
NSArray *cellArray = [sectionData cells];
JVCell *cell = [cellArray objectAtIndex:row];
return [cell cellHeight]; // changed when selected with setExpanded: method
}
Edit 2: I made a Quicktime video of what was happening and extracted screen shots.
What I'm attempting to do is expand a cell, not replace, insert or delete cells. Each cell has one or more subviews. The height of the cell changes depending on whether it's 'expanded' or not. The content view has the subviews added to it, and it's clipToBounds property is YES. When the cells expands or collapses the height value changes along with the frame of the cell (including background view and selected background view). I've logged all the frame values before, during and after expansion, and they are all consistent with their state and position.
Keep in mind that this works normally on iOS 4.3, as shown below:
I don't see any difference in behavior between iOS 5.0 and 4.3.2 in the simulator, or 5.0 on my phone—the cells disappear in the same way on each. (I'd test on 4.2.1 on my older iPod touch but Xcode 4 can't. Grr..) It looks like there's an easy workaround, though: If you do both reloadRowsAtIndexPaths:withRowAnimation: after expanding/collapsing your cells and then the reloadData call after that, it appears to preserve the animation.
Here's a small demo project for this. It's hard to say what the actual problem was—it's just some odd side effect of how UIKit is doing the cell animation. If you subclass [UITableViewCell setAlpha:] you can see that the table view is setting the cell's alpha to 0 and leaving it there. Weird.
Edit: Well that's weird. It wasn't working for a bit (was doing the old behavior, with cells disappearing), but now it's right again. Maybe I was running the wrong version. Anyway, let me know if this works for you.
I had the same issue.
I confirm that using no animation when reloading the row works fine.
But it turns out the issue is caused by returning a cached UITableViewCell in cellForRowAtIndexPath when actually a fresh one is needed.
The doc for reloadRowsAtIndexPaths:withRowAnimation: says:
"Reloading a row causes the table view to ask its data source for a new cell for that row."
Your cellForRowAtIndexPath method is returning locally cached cells.
Returning a brand new cell fixed the issue in my case and no workarounds were needed...
#Javy,
Thanks for your question. I was developing table with similar behaviour: there are text views (UITextView) in my table view cells (UITableViewCell) that are :
expanding if new line is required to display text without scrolling, or
collapsing if new line was removed
So I found the same problem. In iOS 5.x when I was starting to type text it suddenly was becoming invisible. But in iOS 4.x everything works fine.
I have found the solution and it works well for me.
Solution: Just try to replace your animation type UITableViewRowAnimationAutomatic with UITableViewRowAnimationNone when reloading the particular cell.
Some additional code: reload both cell in one moment:
NSMutableArray *indexes = [NSMutableArray arrayWithCapacity:2];
// collapse previous cell
if( previousCell != nil && [previousCell expandable] )
{
if( [previousCell expanded] ) [previousCell setExpanded:NO];
[indexes addObject:previousIndexPath_];
}
// expand new cell
if( [cell expandable] )
{
[cell setExpanded:YES];
[indexes addObject:indexPath];
}
[tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone];
Hope it will help you.
Seems to me like the cell isn't redrawn properly.
Did you try something like:
[cell.backgroundView setNeedsDisplay]
you could try reloading the table view when the animations have completed? at the moment if your animations are fired, and then you call [tableView reloadData] the animations won't be complete, so the frame etc may get out of sync
you could change your set expanded method to take a flag as well as an animation completion block, which could contain the reload code
[cell setExpanded:YES completion:^
//reload code
}];
In:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
you must return a new cell. If cell you don't need to create a new one, you only need:
[tableView beginUpdates];
[tableView endUpdates];
There is no need to call reloadRowsAtIndexPaths.
Okay...
before you
previousIndexPath_ = indexPath;
and after you do all the expanding / contracting of heights etc; you need to do something like
[cellArray replaceObjectAtIndex:previousIndexPath_ withObject:previousCell];
[cellArray replaceObjectAtIndex:indexPath withObject:cell];
which means your cellArray needs to be
NSMutableArray* cellArray;

UITableView discloure indicator going nuts

I have a UITableView (on a UIViewController) which is pushed via a navigationController. Along with pushing, I select with which array i want to populate the table. The code for pushing is like this:
if(self.newView == nil)
{
NewView *viewTwo = [[NewView alloc] initWithNibName:#"Bundle" bundle:[NSBundle mainBundle]];
self.newView = viewTwo;
[viewTwo release];
}
[self.navigationController pushViewController:self.newView animated:YES];
newView.tableArray=newView.arrayWithOptionOne;
[newView.tableView reloadData];
All works well and the table gets reloaded every time. However in the last row of section 0, there is a switch which loads section 1.
The last row of section 1 is tappable (didSelect…) and it loads a modalView. On this last rod I added a disclosure indicator and also the blue background when tapping. The table has sliders, labels, etc. So the customization is quite long:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
static NSString *kDisplayCell_ID = #"DisplayCellID";
cell = [tableView dequeueReusableCellWithIdentifier:kDisplayCell_ID];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:kDisplayCell_ID] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
else
{
UIView *viewToRemove = nil;
viewToRemove = [cell.contentView viewWithTag:1];
if (viewToRemove)
[viewToRemove removeFromSuperview];
UIView *viewToRemove2 = nil;
viewToRemove2 = [cell.contentView viewWithTag:2];
if (viewToRemove2)
[viewToRemove2 removeFromSuperview];
}
if (indexPath.section==0) {
UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row];
[cell.contentView addSubview:cellValueS];
}
if (indexPath.section==0 && indexPath.row==3) {
UIControl *cellValueL = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewLabel] objectAtIndex:0] ;
[cell.contentView addSubview:cellValueL];
}
if (indexPath.section==1 && indexPath.row==0){
UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row] ;
[cell.contentView addSubview:cellValueS];
}
if (indexPath.section==1 && indexPath.row==1) {
UIControl *cellValueS = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewKey] objectAtIndex:indexPath.row] ;
[cell.contentView addSubview:cellValueS];
UIControl *cellValueL = [[[arrayTable objectAtIndex:indexPath.section] objectForKey:kViewLabel] objectAtIndex:0] ;
[cell.contentView addSubview:cellValueL];
}
if (indexPath.section==1 && indexPath.row==2) {
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
So far also works ok.
The problem is that when I go back to the previous view and select another option to populate the table, when it's pushed again, I see the disclosure indicator and blue selection background on other rows on the same section. I've observed that it depends on where the table is scrolled.
I've tried to understand why does it happen, but i can't. I've somehow solved the problem by setting newView to nil and releasing it and then allocating it again before it gets pushed again.
Am I doing something wrong here? or why is the disclosure indicator and tapping background appearing where they are not supposed to be?
Thanks in advance!
action of the switch
-(void)extraOptionsSwitchAction:(id)sender{
switch(extraOptionsSwitch.isOn) {
case 1:
// [self.tableView beginUpdates];
[self.tableView insertSections: [NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
//[self.tableView reloadData];
// [self.tableView endUpdates];
break;
case !1:
// [self.tableView beginUpdates];
[self.tableView deleteSections: [NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
// [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadData];
// [self.tableView endUpdates];
break;
}
}
It has to to with reusing cells. You probably don't differentiate between the different cell types in your cell creation method - so one cell that went offscreen can easily be reused for another (different type) cell. Further, you seem to add subviews over and over again - only do that when you instantiate the cell (with alloc/int), and not when configuring.
Also, for different cell types, use different identifiers (you didn't show this code).
The programming guides have good example on table views and their cells and reuse pattern. It's worth reading a couple of times - it's easy to get wrong and is a main topic for performance tuning.
Edit
Now that you added more code, another problem seems to be here:
if (indexPath.section==1 && indexPath.row==2) {
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
You are missing an else part. The selectionStyle and accessoryType are set to what they were set to before - you miss to configure the cells correctly for all other cells than that special one.
Each cell type should really get its own identifier though. If the adding/removing of subviews work as expected is hard to tell from that code.
One thought: As you aren't really reusing a lot of the cells here anyhow you could even disable the reuse by changing
static NSString *kDisplayCell_ID = #"DisplayCellID";
cell = [tableView dequeueReusableCellWithIdentifier:kDisplayCell_ID];
to
static NSString *kDisplayCell_ID = nil;
This would just always produce a new cell. I wouldn't recommend this in the general case, though.
This is due to cellReusability, and it has, for a long time, wasted so many developers' time and effort. If you knew the concept of cell reusability, you would know that while scrolling, the index of the row and sections remain the same (although you expect it to be different for a different position on the uiTableView).
The only way is to subClass the UITableViewCell and create your own CustomUITableViewCell, and implement that with the disclosure indicator, or resist your input to just a small TableView that fits the screen and make scrollable = NO.