deleting a row out of table view - iphone

I am having trouble with my tableView crashing when I try and delete a row out of the table View. The method gets called correctly as the change is made in the database correctly. The error which I receive is:
Invalid update: invalid number of rows in section 0.
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSManagedObject *objectToDelete = [fixedArray objectAtIndex:indexPath.row];
[context deleteObject:objectToDelete];
[delegate saveContext];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
fixedArray = ([self mondayData]); // this is fetching the data for the array that I supply to the table view
[self.tableView numberOfRowsInSection:[fixedArray count]];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [fixedArray count];
}

Your - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section method is likely not returning the appropriate number of rows. It should return the previous number of rows minus the number of rows that have just been deleted.
Also, if there are no more rows in the section, you must delete that section from the UITableView.

You need to include
[tableView beginUpdates];
and
[tableView endUpdates];
in your code. These two methods will prevent the UITableView from crashing while you delete or insert rows.
Put beginUpdates before you delete the tableView's row, and then endUpdates once you're all done.
Here's the documentation.

[tableView beginUpdates];
if (editingStyle == UITableViewCellEditingStyleDelete) {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObject *object = [fixedArray objectAtIndex:indexPath.row];
[object setValue:#"No" forKey:#"selected"]; // this works and persists into the database
[delegate saveContext];
fixedArray = ([self mondayData]);
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
}
[tableView endUpdates];
[self.tableView reloadData];
This worked for me in the end.

Related

No update or numberOfRowsInSection after delete with commitEditingStyle

My table doesn't update after removing an item with Edit / Delete or the swipe-delete gesture. If I do Edit / Delete, the Delete button doesn't disappear. It stays there in a pressed/stuck state. When I then click Done, the Delete button goes away. A screenshot of this is attached at the bottom of this post.
My numberOfRowsInSection code is executed when the app is started, but not after the deletion of an item.
I'm using a UITableViewController. The definition in my .h file:
#interface BNVFavoritesTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>{
BNVAppDelegate *appDelegate;
IBOutlet UITableView *myTable;
}
#property (retain, nonatomic) IBOutlet UITableView *myTable;
#end
Here's the relevant code from my .m file:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"number of rows:\t%d", [appDelegate.favoritesArray count]);
return [appDelegate.favoritesArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Get the object from the array.
BNVFavorite *favoriteObj = [appDelegate.favoritesArray objectAtIndex:indexPath.row];
//Set the name.
cell.textLabel.text = favoriteObj.name;
// Set up the cell
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// If row is deleted, remove it from the list.
if (editingStyle == UITableViewCellEditingStyleDelete){
NSLog(#"before delete\t%d", [appDelegate.favoritesArray count]);
BNVFavorite *selectedObject = [appDelegate.favoritesArray objectAtIndex:indexPath.row];
NSString *selectedName = selectedObject.name;
// delete from sqlite database
[appDelegate removeFavoriteFromDB:selectedName];
// delete from memory array
[appDelegate.favoritesArray removeObjectAtIndex:indexPath.row];
// delete in user interface
[myTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
NSLog(#"after delete\t%d", [appDelegate.favoritesArray count]);
}
}
When deleting, I see 'before delete' and 'after delete' messages in my log (as expected), but no 'number of rows' messages.
My datasource and delegate outlets from the Table View are connected to the TableViewController class. I also tried doing this in the ViewDidLoad method, but that didn't make a diferent. Forcing a [myTable reloadData]; at the end of my commitEditingStyle is also not helping.
Finally, here's a screenshot of that 'stuck' delete button.
http://i.stack.imgur.com/ukUu0.png
Clicking it a few times causes an NSRangeException/out of bounds error, indicating that the code from commitEditingStyle is executed.
After hours of searching, I found the problem. Turns out the referencing outlet from the tableview in the storyboard to myTable in my controller class didn't exist anymore. I must have removed it accidentally. I found out about it when I noticed the code started working when I replaced myTable with self.tableView.
You need to add your delete animation between beginUpdates and endUpdates.
[myTable beginUpdates];
[myTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[myTable endUpdates];
Just check your connection in connection inspector for your table.
or if it is properly connected then
Reload your table after deleting record
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// If row is deleted, remove it from the list.
if (editingStyle == UITableViewCellEditingStyleDelete){
NSLog(#"before delete\t%d", [appDelegate.favoritesArray count]);
BNVFavorite *selectedObject = [appDelegate.favoritesArray objectAtIndex:indexPath.row];
NSString *selectedName = selectedObject.name;
// delete from sqlite database
[appDelegate removeFavoriteFromDB:selectedName];
// delete from memory array
[appDelegate.favoritesArray removeObjectAtIndex:indexPath.row];
// delete in user interface
[myTable deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
NSLog(#"after delete\t%d", [appDelegate.favoritesArray count]);
[myTable reloadData];
}
}

UITableView crashes when trying to delete a cell and section

I've been working on creating a UITableView that has its content loaded from a NSUserDefaults object. Whenever I attempt to delete a cell/section, however, the program crashes and spits out the following:
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1030
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).
No matter how much I read up on this error and try to fix it, I've been stuck here for the past few hours. Here is my method that is called when the user taps the "delete" button:
(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//[[[NSUserDefaults standardUserDefaults] objectForKey:#"rawArray"] removeObjectAtIndex:indexPath.row];
//[[[NSUserDefaults standardUserDefaults] objectForKey:#"rawDates"] removeObjectAtIndex:indexPath.row];
NSMutableArray *rawArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"rawArray"];
NSMutableArray *rawDates = [[NSUserDefaults standardUserDefaults] objectForKey:#"rawDates"];
[rawArray removeObjectAtIndex:indexPath.row];
[rawDates removeObjectAtIndex:indexPath.row];
[[NSUserDefaults standardUserDefaults] setObject:rawArray forKey:#"rawArray"];
[[NSUserDefaults standardUserDefaults] setObject:rawDates forKey:#"rawDates"];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
}
}
and here are the methods used to determine number of rows and cells:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [[[NSUserDefaults standardUserDefaults] arrayForKey:#"rawDates"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return [[[NSUserDefaults standardUserDefaults] arrayForKey:#"rawDates"] objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
The last method in there returns a one because, as of right now, I plan on only have one cell per each section. Thank you for taking the time to look over here, and I really hope you can help me out! :/
Check out the Batch Insertion, Deletion, and Reloading of Rows and Sections
Basically you need to put any calls of these method
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
between
- (void)beginUpdates;
- (void)endUpdates;
e.g.
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
Your dataSource also needs to reflect the changes by the time endUpdates is called
Personally I like to make a category to give a block based wrapper around this to
stop me forgetting to call endUpdates
it allows indentation to look right / be automatic
Category on UITableView
#interface UITableView (PSAdditions)
- (void)ps_updates:(void (^)(void))updateBlock;
#end
#implementation UITableView (PSAdditions)
- (void)ps_updates:(void (^)(void))updateBlock;
{
[self beginUpdates];
if (updateBlock) { updateBlock(); }
[self endUpdates];
}
Which would look like this
[tableView ps_updates:^{
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
}];

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

delete row i uitableview working but cant reflect always on iphone

i can successfuly delete data from tableview , but when i go to main menu and come back then i see all the old data,
how to make data consistent , i.e once deleted it will be gone forever
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (DatabaseTestAppDelegate *)[[UIApplication sharedApplication] delegate];
{
appDelegate.favDetail = [[NSMutableArray alloc] initWithObjects:#"1", #"2",#"4",nil];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
appDelegate = (DatabaseTestAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *cc=[appDelegate.favDetail objectAtIndex:indexPath.row];
NSLog(#" vale is %d",indexPath.row);
// Configure the cell...
NSArray *theParameters = [cc componentsSeparatedByString:#","];
NSLog(#"array is %#",cc);
NSLog(#"arraytheParameters is %#",theParameters);
cell.text=cc;//theParameters;
return cell;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{ NSLog(#"matrix is her%#",appDelegate.favDetail);
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[appDelegate.favDetail removeObjectAtIndex: indexPath.row];
[tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject: indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
/*
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
} */
}
- (void)viewWillAppear:(BOOL)animated
{ [tableView reloadData];
[super viewWillAppear:animated]; // no use , it shows old data
}
thanks
If you are looking to save the state of your model beyond the life of your table view controller, there are few things you can do. One is to write the array to a file in the documents directory and read it back on reload. This would work well will small sets of data. But if you are going to use a large data set, you have to use Core Data.
As for this specific case, you are reinitializing the data on every viewDidLoad. I suggest you do this in viewDidLoad –
...
if ( appDelegate.favDetail == nil ) {
appDelegate.favDetail = [[NSMutableArray alloc] initWithObjects:#"1", #"2",#"4",nil];
}
...
This will make sure that you don't reinitialize it.
you have to delete the data in both your view and your model
Check out the place where appDelegate.favDetail is getting data from...
While deleting you are removing from appDelegate.favDetail but When you go to main menu and come back you are reassigning the values to appDelegate.favDetail...
Checkout that appDelegate.favDetail only gets the value once.. or another option is you remove the data from the main source from where the favDetail gets the value
Happy iCoding....

iPhone: Crash When Deleting UITableView Rows

I am new in iPhone development. I am developing an application that fetches a value from a database and displays it in a table view. I want to delete table rows one by one but the rows do not delete and the application crashes.
Here is my row deletion code:
- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(editingStyle == UITableViewCellEditingStyleDelete) {
SanjeevKapoorAppDelegate *appDelegate =(SanjeevKapoorAppDelegate *)[[UIApplication sharedApplication] delegate];
list *animal =[appDelegate.list1 objectAtIndex:indexPath.row];
[appDelegate deleteCoffee];
[self.tableView reloadData];
//Delete the object from the table.
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
I also delete all rows with this action:
-(IBAction)deletebtn:(id)sender{
SanjeevKapoorAppDelegate *appDelegate =(SanjeevKapoorAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate deleteCoffee];
[self.tableView reloadData];
}
How do I properly implement delete in an UITableView?
You need to change:
[self.tableView reloadData];
//Delete the object from the table.
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
to just:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
You are crashing because you're changing your data model to delete the row, then reloading the table such that the row no longer exist then telling the table to delete the non-existant row.
You don't have to call reload data in this instance because the table has already altered itself visually. You only call reload when a change in the data model forces a change in the table not when a table itself changes the data model.
Try wrapping the call to deleteRows in beginUpdates and endUpdates:
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[appDelegate deleteCoffee];
[self.tableView endUpdates];
I assume deleteCoffee affects how the table is populated. That must go between the update wrappers.
Or you can use reloadData without the other calls:
[appDelegate deleteCoffee];
[self.tableView reloadData];