UITableView "swipe to delete" function freezes - iphone

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?

Related

At canEditRowAtIndexPath Method, reloadData of UITableView not work properly?

In my application, I reload my TableView ([tablView reloadData];) after delete row from TableView then canEditRowAtIndexPath Method alway call for (pervious) total number Of Rows.
For Example:
If i have 5 Rows on my TableView, then i delete 1 row from tableView. After deleting, I reload my TableView ([tablView reloadData]) but canEditRowAtIndexPath Method calls 5 time instead of 4 times ??
So i always got Following Error:
Terminating app due to uncaught exception 'NSRangeException', reason: '* **-[__NSArrayM objectAtIndex:]: index 5 beyond bounds [0 .. 4]'
I also tried to reload table after some delay (using NSTimer) but it also not worked for me.
I put some code here:
I apply canEditRowAtIndexPath on specific row which #"status" isEqualToString:#"directory" such like,
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%d", self.listOfSounds.count);
// Return NO if you do not want the specified item to be editable.
if([[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:#"status"] isEqualToString:#"directory"])
return YES;
else
return NO;
}
Code of delete row:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:#"main_id"]]; /// delete record from DB
[self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array
[self updateListofSoundsFile]; /// Custom method
}
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO; // i also tried to return YES;
}
Here updateListofSoundsFile is my custom method code is :
-(void)updateListofSoundsFile
{
if(self.listOfSounds.count > 0)
[self.listOfSounds removeAllObjects];
self.listOfSounds = [self.sql_ getAllDataFromAudioTable]; // get all record from DB
NSLog(#"%d",self.listOfSounds.count);
[self.tblView reloadData];
}
Please Give any suggestion, How can i solve this issue ?
Thanks :)
you need to remove raw from tableview also befor remove item from array and reload data using this line becouse remove item from array but not tableview.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:#"main_id"]]; /// delete record from DB
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array
[self updateListofSoundsFile]; /// Custom method
}
}
I ran into this same problem. The issue was that I deleted the object of the cell but when I used the reloadData method of the tableView, my canEditRowAtIndexPath method was not being called resulting in being able to edit cells that I do not want edited. The true fix was not calling the deleteRowsAtIndexPaths method, but the [tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; method.
Basically here is what was happening:
When I called reloadData:
The raw data was not being removed from the tableView as Nitin said. Therefore this is not the solution.
When I called deleteRowsAtIndexPaths:
iOS detected a discrepancy between the underlying data and the number of cells (because I had already removed the underlying object). The result was a crash which is also not the solution (obviously).
Now for The Fix!
When I called reloadRowsAtIndexPaths:
This caused the tableView to simply reload that single cell AND it got rid of the raw data. This is the solution.
Rather than removing the dataSource object, then trying to remove the cell that is essentially backed by nothing at this point (which causes a crash), simply remove the dataSource object, then reload that indexPath of the tableView
Here is the general format of the method:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[myDataSourceArray removeObjectAtIndex:indexPath.row];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
This is the first time I ran into the issue with the residual raw data that is not removed by simply calling the reloadData method. This is certainly the most elegant solution that I have seen thus far.
Happy Coding! I hope this helps.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.sql_ deleteSoundFileAudioTableWhereMainID:[[self.listOfSounds objectAtIndex:indexPath.row] objectForKey:#"main_id"]]; /// delete record from DB
[self.listOfSounds removeObjectAtIndex:indexPath.row]; /// delete record from Array
[self updateListofSoundsFile]; /// Custom method
}
[self.tblView reloadData];
}
When it comes to me, I analysed as below:
As commented by rmaddy on Nitin Gohel's answer:
You should always remove the data from the data source before updating the table.
I feels this is the ideal way.
If you are going to call reloadData, there is no reason at all to first call deleteRowsAtIndexPath.
This is also looks correct.
I analysed ambiguity, if I write reloadData its crashishing but once I write deleteRowsAtIndexPath it worked well.
Hope someone will emphasise on this issue for its causes etc.
the 'removeObjectAtIndex:indexPath' takes some time and I suspect your [self.tblView reloadData] is being called early. I tried a sample code and found success with [UiTableView beginUpdates] and [UiTableView endUpdates] you may also avoid crash if you put a little delay before the reloading or deleting rows haven't tried it though
[tableTable beginUpdates];
[tableArray removeObjectAtIndex:indexPath.row];
[tableTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableTable endUpdates];

UITableView commitEditingStyle without deleting cell

I have small problem with my conception of deleting rows in UITableView. After user deletes a row i do not want to fire:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
Instead I want to change edited cell text and background without hiding it. My approach works quite well:
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSMutableArray *previous_points = [self.trip_arrayOfAllPoints mutableCopy];
[previous_points removeObjectAtIndex:indexPath.row];
self.trip_arrayOfAllPoints = nil;
self.trip_arrayOfAllPoints = [[NSMutableArray alloc] initWithCapacity:[previous_points count]];
self.trip_arrayOfAllPoints = [previous_points mutableCopy];
self.trip_arrayOfAllPointsEDITED = [[NSMutableArray alloc] initWithCapacity:[previous_points count]];
self.trip_arrayOfAllPointsEDITED = [previous_points mutableCopy];
//[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
self.trip_isArrayOfAllPointsEDITED = YES;
}
But after deleting a row it does not commit animation of dissapearing "DELETE" label on current cell. Is there a way around "Apple way" of deleting rows?
EDIT - I've worked it out
It's pretty simple and plain. Just replace deleteRowsAtIndexPaths with:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
After this "delete" animation disappears and cell is still in it's place.
You mean that "Delete" button stays, even if you pressed it? On my iOS 5.1 emulator after
pressing "Delete" with empty:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
"Delete" button disappears.
I'm using this code and it's working fine
//self.selectedMessageIndex is NSIndexPath object declared in header file
//self.attachments is a NSMutableArray Object
[self.attachments removeObjectAtIndex:self.selectedMessageIndex.row];
[tblvAttachmentsList deleteRowsAtIndexPaths:[NSArray arrayWithObject:self.selectedMessageIndex]
withRowAnimation:UITableViewRowAnimationLeft];
[tblvAttachmentsList reloadData];
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
This is going to remove the delete button with a nice animation. Invoke, when you know you are not going to delete the row:
func tableView(tableView: UITableView, commitEditingStyle editingStyle:UITableViewCellEditingStyle, forRowAtIndexPath indexPath:NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
//An action happens here. If it was successful, page is refreshed
//If the action fails, cell stays. I am showing an error and:
self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation:.Automatic)
}
}

How to give action to 'Delete' in editButtonItem?

I've in my tableview i've
self.navigationItem.rightBarButtonItem = self.editButtonItem;
clicking on the minus button shows Delete button. I want to know how to give an action to this Delete button.
Tableview shows a list of items from sqlite database.I'm using Xcode 4.2
The delete button is already linked to your table view, and tapping it will send tableView:commitEditingStyle:forRowAtIndexPath: to your table view's data source. You do your deletion here.
This method is normally included in the template for UITableViewController subclasses.
If you look in to the UITableViewDataSource Protocol Reference you will find in there tableView:commitEditingStyle:forRowAtIndexPath:.
Asks the data source to commit the insertion or deletion of a
specified row in the receiver.
In this method you will get the index path for the cell to delete. You have to remove the corespondent element in four data source. And you also need to remove the table view cell.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
When you press delete button it will automatically call this delegate method of UITableView:
- (void)tableView:(UITableView *)tableView commitEditingStyle:( UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath.
{
// Check if it's a delete button or edit button...
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Update the array and table view.
[eventsArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
// Commit the change.
NSError *error;
if (![managedObjectContext save:&error])
{
// Handle the error.
}
}
}
Implement tableView:commitEditingStyle:forRowAtIndexPath: in your table view data source (presumably your table view controller). See the docs on that method, or any of several Apple sample code projects (including what you get from the Xcode "master-detail app" template) for details & example usage.
I would add that you should make sure you are reloading the table data so it can update on the screen. Otherwise it will look like it didn't do anything.
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.myMutableArray removeObjectAtIndex:indexPath.row];
[self.tableView reloadData];
}

How to delete row from table view?

I have a table view, data were retrieved from database and display in the table rows.
I have a remove button at the top navigation bar from removing table row.
When button is tapped, a red circle delete icon will appear.
After I select delete, it gave me and error call "Program received signal SIGABRT" at the [tableViewDelete rows......]
This is my code.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
Object = [array objectAtIndex:indexPath.row];
[ClassA ClassAMethod:[appDelegate getDBPath] :Object.ID];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
How do I remove a row from the table view?
Does anybody have any ideas or has anybody else achieved anything similar?
Thanks
I assume this line:
[ClassA ClassAMethod:[appDelegate getDBPath] :Object.ID];
deletes your object from database, while table is filled from some array instance - you need to delete an object from that array as well to maintain data integrity (array must be NSMutableArray instance):
Object = [array objectAtIndex:indexPath.row];
[ClassA ClassAMethod:[appDelegate getDBPath] :Object.ID];
// Add the following line
[array removeObjectAtIndex:indexPath:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
try this code in editing delegate method of tableview:--
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[[self displayedObjects] removeObjectAtIndex:[indexPath row]];
// Animate deletion
NSArray *indexPaths = [NSArray arrayWithObject:indexPath];
[[self tableView] deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
i hope this can solve your problem

Smooth reload of uitableview data when rows are deleted

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