I have a UITableViewController with an Edit button. When this is clicked, the user can delete or add rows to the UITableView. Deleting rows works fine. But when I want to add a new row, I get a short animation of an empty cell coming from the left and when the animation is over, the table view looks exactly as it looked before the method was called. When I add a new cell, I add a new object to the data array that feeds my table view and then add the cell. That data array gets updated. So if I call [tableView reloadData] after I have added the new cell, I get to see the new cell but without any animation. And I really would like to have the animation as well.
I have a working example of the same thing. I realized that after tableView:commitEditingStyle:forRowAtIndexPath: gets called, the table view's data source method tableView:cellForRowAtIndexPath: gets automatically called. In my case, it doesn't. I guess that's the reason why I'm not seeing the new cell. Any ideas why this is happening?
This is my `tableView:commitEditingStyle:forRowAtIndexPath:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
[self.tableData removeObjectAtIndex:[indexPath row]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.tableData forKey:self.key];
[defaults synchronize];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UITextField *textField = (UITextField *)[[cell contentView] viewWithTag:kTextFieldTag];
NSString *textFieldText = [textField text];
if (textFieldText != nil)
{
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
NSString *string = [[NSString alloc] initWithString:textFieldText];
[self.tableData addObject:string];
[string release];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.tableData forKey:self.key];
[defaults synchronize];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
// If reloadData is being called, the new cell is displayed but without the animation
// [tableView reloadData];
}
else
{
// Display alert view
// Code for displaying an AlertView
}
}
}
Try wrapping your insert call with [tableView beginUpdates] [tableView endUpdates]. From the docs:
If you do not make the insertion, deletion, and selection calls
inside this block, table attributes such as row count might become
invalid.
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
[tableView endUpdates];
I'm having this same issue. From what I can tell, the UITableView only calls cellForRowAtIndexPath if it thinks the cell being changed is visible. Since you are adding a new cell I'm guessing the table does not think it's visible and therefore does not call the method. Jaminguys solution works for me, but it sounds a bit like a bug in UIKit.
This method does work if you are inserting cells in the middle of the table view, incidentally.
Related
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];
I have a view controller that manages a table view. My understanding is that a table cell will be deselected automatically if I push another viewcontroller and then pop back to the table view.
However, in the same class (that I use a few times), there is one instance of the class when the cell is deselected but not animated (it'll just turn blue and then back to normal without animating). Why did this happen? I have a few instances of this class but it only happens to one of them. What might be causing this?
From my experience cells are not automatically deselected if you push/pop a view controller (at least not when using a navigationcontroller), unless you add some code te deselect it !
It may also be automatically deselected if you are doing a [tableView reloadData] in viewWill/DidAppear (or in a process started in these methods).
Did you try to add something like that in viewDidAppear ?
NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
if (indexPath != nil) {
[tableView deselectRowAtIndexPath:indexPath animated:YES]
}
NSIndexPath *indexPath = [tableView indexPathForSelectedRow];
if (indexPath != nil) {
[tableView deselectRowAtIndexPath:indexPath animated:YES]
}
this you have to write in didselectRowAtIndexPath method
You can reload the Tableview again.
In your viewWillAppear
[yourTableView reloadData];
Or if you dont want to disturb your Datasource try this
NSArray *array = [yourTableView visibleCells];
for(UITableViewCell *cell in array)
{
cell.selected = NO;
}
I am trying to reload a uitableview when it scrolls to the bottom of the screen. I delete the first few rows and add more rows to the bottom. Before the news rows are added to the uitableview's data source, i call the [tableview reloaddata] method. This is because i want the tableview to display the row which were previously visible on it.
It reloads the data correctly but there is a sudden jerk in the tableview. It flashes which doesn't give a nice user experience. So my question is
How to update the uitableview
when few rows from the top are
deleted without having the
jerking/flashing effect?
The current visible row should be retained in the refreshed view also.
Any ideas? There are no crashes as i update the data source correctly.
TIA,
Praveen S
delete the data from the data source in tableView delegate.
-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = [keys objectAtIndex:indexPath.section];
NSMutableArray *nameSection =[names objectForKey:key];
int itemID=item.ID;
if ([nameSection count]==1) {
[self.keys removeObjectsInArray:[NSArray arrayWithObject:key]];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
else {
[nameSection removeObjectAtIndex:indexPath.row];
[self.names setValue:nameSection forKey:key];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
check this too
I can't figure out why my tableView isn't updating after I tap the delete button.
Once I click it, the table view "freezes". If I click another row, so that the tableview goes to another level of the hierarchy and click back, I can see that the item has been deleted and everything works fine.
Here is my code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
//[tableView beginUpdates];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Do whatever data deletion you need to do...
[tableView beginUpdates];
NSManagedObject *obj = (NSManagedObject *)[entityArray objectAtIndex:indexPath.row];
[managedObjectContext deleteObject:obj];
NSError *error;
[managedObjectContext save:&error];
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self viewWillAppear:YES];
}
//[tableView endUpdates];
}
Any input on this problem would be appreciated.
Thanks.
Found same issue and stumbled upon this thread. But the reason for the tableview freeze issue was different in our case.
For the sake of posterity:
The UITableViewCell which goes into Edit mode to display the "insert" or "delete" buttons should never have its userInteractionEnabled property set to "NO".
By correcting this, the same tableview freezing issue was fixed for us.
I can't see a call to [tableView endUpdates] matching the [tableView beginUpdates] that is at start of the if.
Could it be for this reason that your table freezes?
I am new in objective-c i want ur help
my question is that i have tableview with 10 cell each cell is field with some data that are come from tabase later i change some of the cell value from table view and now i want to read this all cell value from table view after table view reload with new value then how can i do
how can i stored it in new array
i am trying to do something like this it is correct or not if not then how can i do
-(void)viewWillAppear:(BOOL)animated // after new value will insert
{
[tableView reloadData];
NSArray *visibleRowsArr = [tableView indexPathsForVisibleRows];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[visibleRowsArr objectAtIndex:0]];
}
in viewwillappear
[tableview reloadData] should be at the end of viewwillappear that is before }
It's so easy, you can try use the same array from which you are reloading the whole table.
Because after all that array would have been updated so there is no need to read the records from TableViewCells but try it using with Array.
like :
int AtOurWish =5;
-(void)viewWillAppear:(BOOL)animated // after new value will insert
{
[super viewWillAppear:animated];
[self.YourArray objectAtIndex:AtOurWish];//Index At which you want to access the array
[tableView reloadData];
NSArray *visibleRowsArr = [tableView indexPathsForVisibleRows];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[visibleRowsArr objectAtIndex:0]];
}
Otherwise you edit you question since it's not much clear!!!