I try to manage to delete a row from an UITable which is part on an UIViewController. I use the Edit button in the navigation bar. Hitting it will put the table rows in edit mode. But when a delete button in a row is pressed I get an error ...'Invalid update: invalid number of rows in section 0…. when using the following:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:YES];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSMutableArray *work_array = [NSMutableArray arrayWithArray:self.inputValues];
[work_array removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
What do I miss here? The Apple documentation seems to be outdated somehow.
Thanks
The problem is simple. You are not updating your data model properly before deleting the row from the table.
All you do is create some new array and delete a row from that. That's pointless. You need to update the same array used by the other data source methods such as numberOfRowsInSection:.
The issue you are having is that you are not directly updating your table's data source. You first create a completely new array called work_array based on your data source (I'm assuming it's self.inputValues) and then you remove an item from it, and then try to delete a row, but your tableView's data source still contains the item you intended to remove.
All you need to do is ensure that self.inputValues is a mutable array and directly remove the object at the index for that array, like this:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.inputValues removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
I hope that helps!
Related
In my app I have a Table view with values from a mapkit. I can edit the table, delete the row, but when the app starts over, the same deleted rows are still there....How can I fix this? The code for the editing:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_locations removeObjectAtIndex:[indexPath row]];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadData];
}
Any tips? Thank you
Load the data from core data using a NSFetchedResultsController.
Implement the delegate function to update your views when change occur.
When you delete something delete enqueue a block to delete it from core data. (if you are using NSPersistentContainer use performBackgroundTask:).
Don't update your views. This will happen automatically because of the delegate callback that you implemented in step 2.
I am trying to delete a cell and remove a section from a UITableView with the following code:
[self.tableView beginUpdates];
[arraymasterFeedFullDetails removeObjectAtIndex:cellSelectedIndexPath.section];
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:cellSelectedIndexPath.section]withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Here,cellSelectedIndexPath is NSIndexPath variable which is pointing to the section is currently selected. arraymasterFeedFullDetails is my datasource and only one row per each section.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [arraymasterFeedFullDetails count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
When you have a data source(arraymasterFeedFullDetails in your case), the thing you need to do to delete an item, is to remove object from data source and then reload the table.
You can reload the table using [self.tableView reloadData];
So your code would be like this:
[arraymasterFeedFullDetails removeObjectAtIndex:cellSelectedIndexPath.section];
[self.tableView reloadData];
When you have a data source(arraymasterFeedFullDetails in your case), the thing you need to do to delete an item, is to remove object from data source and then either reload the whole table, or, remove the cells from the datasource with animation.
This in general will produce a visually better result.
The reloadData method will reload the whole table, without animation.
Currently shown cells will be simply redrawn. E.g.:
[self.tableView reloadData];
You won't need to update the tableview itself, as this will be simply redrawn.
In order to remove just "edited away cells", with an animation effect, you can use the method deleteRowsAtIndexPaths: withRowAnimation:
E.g.:
// Overridden to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_list2 removeObjectAtIndex:indexPath.row]; // remove row from array
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade]; // remove cell from UITableView
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
You could also remove rows from your mutable array, then call
deleteSections:withRowAnimation:
between beginUpdates and endUpdates in order to delete a whole section from your tableview;
In both animated deletion approaches, you will need to make sure that the data source has the same count of the tableview cells (after the deletions) before doing any animation which will update the tableview.
I have created a table view in iOS and implemented delete row functionality. Everything is working. I have one doubt,
Consider the following case,
Suppose the table has 15 rows, and if I delete row no 10. Sometimes the cells from the top (1-9) animate from top to bottom to the position of row no 10. Sometimes the cells from the bottom(11-15) animate to the top. This occurs in random.
This is the code for deleting
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#">>> Entering %s <<<", __PRETTY_FUNCTION__);
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[[self contents] removeObjectAtIndex:[indexPath row]];
NSArray *indexPathsToRemove = [NSArray arrayWithObject:indexPath];
[tableView deleteRowsAtIndexPaths:indexPathsToRemove withRowAnimation:UITableViewRowAnimationAutomatic];
}
NSLog(#"<<< Leaving %s >>>", __PRETTY_FUNCTION__);
}
And between this is tutorial I am following
You can download the project from this link.
Is there anyway to control this behaviour.
Thanks in advance
You can control it with
withRowAnimation:UITableViewRowAnimationAutomatic
There are various option available
UITableViewRowAnimationBottom
UITableViewRowAnimationFade
UITableViewRowAnimationRight
...
Actual method is:
[mainTableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
I want to delete a row from my tableview. I cannot find a solution that works from the other simialr questions here.
I know I need to use the following code, But I cant seem to figure out how to properly finish this line of code to make it work.
[dailyIncomeArray removeObjectAtIndex:indexPath.row];
But what goes where is says "dailyIncomeArray"?
[what-goes-here removeObjectAtIndex:indexPath.row];
I have a getData method that populates my tableview. Next I want to be able to swipe to the left and hit that red delete button. Thanks in advance for your help!
Heres the rest of the method
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[dailyIncomeArray removeObjectAtIndex:indexPath.row];
[self.tableView reloadData];
//[tableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObject:results] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
Here's the error I'm receiving. I don't understand what this means.
No visible #interface for 'NSArray' declares the selector 'removeObjectAtIndex:'
I've used the sdk standard code for deleting however it crashes once I press the delete button.
I am using this code
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[tableFavoritesData arrayWithObject:indexPath] withRowAnimation:YES];
}
}
I tried with both NSMutableArray instead of tableFavoritesData however nothing works.
Well, basically what you want to do is:
Delete the row from the data source (array).
Tell the table view that you have deleted a row from the data source.
Correct code should probably look like that:
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableFavoritesData removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
EDIT: I didn't notice another error.
You need to specify the type of animation, not just pass YES or NO. For example: UITableViewRowAnimationFade. Check out possible UITableViewRowAnimation values here.
EDIT 2: For the comment below (comment formatting suck):
Check out NSNotificationCenter in the docs, especially addObserver:selector:name:object: and postNotificationName:object: methods.
In your other view controller (probably viewDidLoad method):
[[NSNotificationServer defaultCenter] addObserver:self selector:#selector(deletedRow:) name:#"RowDeleted" object:nil];
-(void) deletedRow:(NSNotification*) notification
{
NSDictionary* userInfo = [notification userInfo];
NSIndexPath indexPath = [userInfo objectForKey:#"IndexPath"];
// your code here
}
and while deleting the row:
if (editingStyle == UITableViewCellEditingStyleDelete) {
...
[[NSNotificationServer defaultCenter] postNotificationName:#"RowDeleted" object:self userInfo:[NSDictionary dictionaryWithObject:indexPath forKey:#"IndexPath"]];
}
Just remember that you need to remove observer from notification center when you dealloc the other UIViewController:
[[NSNotificationServer defaultCenter] removeObserver: self];
Hope I didn't make much errors, I don't have access to XCode atm.
If you looked at the console, it will most probably tell you that your model (your data structure) doesn't match what the table expects. I.e. your delegate method
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
must return one less than before.
Also, [tableFavoritesData arrayWithObject:indexPath] looks very strange and is probably not what's expected. Maybe you want [NSArray arrayWithObject:indexPath] here. And remove the data from your model first.