problem while deleting the row of a grouped table - iphone

hii every one
i am using following code to delete a row in the rgouped table view
- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if(editingStyle == UITableViewCellEditingStyleDelete) {
//Get the object to delete from the array.
insertUpdateDelete *objInsertUpdateDelete = [appDelegate.arrObjects objectAtIndex:indexPath.row];
[appDelegate DeleteRecord:objInsertUpdateDelete];
//Delete the object from the table.
[tableView1 deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
}
but its crashing at the line
[tableView1 deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
crash log is:
2011-05-20 19:21:20.233
iICS[10744:207] * Assertion failure
in -[UITableView
_endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:995
2011-05-20 19:21:20.235 iICS[10744:207]
*** Terminating app due to uncaught exception
'NSInternalInconsistencyException',
reason: 'Invalid update: invalid
number of rows in section 0. The
number of rows contained in an
existing section after the update (3)
must be equal to the number of rows
contained in that section before the
update (3), plus or minus the number
of rows inserted or deleted from that
section (0 inserted, 1 deleted).'
can any buddy help me? thanx in advance

Make sure that your data source is reflecting the changes you are making before calling deleteRowsAtIndexPaths:. I see that you are calling [appDelegate DeleteRecord:objInsertUpdateDelete]; but if your data source is not getting its records directly from the appDelegate and getting them from maybe an array in your class you also need to remove it from that array.
As a side note your design pattern for using the app delegate may be like a "ball of mud". Is it good practice to use AppDelegate for data manipulation and Handling?

You need to first check if the row you're deleting is the only row in a section.

Look in your method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
Does this method always return the correct row count? It seems you're NOT removing the row from whatever datasource is backing your section.
EDIT:
It's possible you are doing the delete, but it has not completed (or committed) at the time your table's dataSource is asking for the new rowcount. You might need to delay your [tableView deleteRowsAtIndexPath:] until the database commits.

Related

Delete Tableview's Row from Detailview

I have used storyboard in my application in my detail view for UITableView i passed tableview to detail view to be able to delete this row depend on something action but give me below error
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (4) must be equal to the
number of rows contained in that section before the update (4),
plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted)
and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
If you delete the last row in your table, the UITableView code expects there to be 0 rows remaining. It calls your UITableViewDataSource methods to determine how many are left. Since you have a "No data" cell, it returns 1, not 0. So when you delete the last row in your table, try calling -insertRowsAtIndexPaths:withRowAnimation: to insert your "No data" row.
What you need to do is :
// tell the table view you're going to make an update
[tableView beginUpdates];
// update the data object that is supplying data for this table
// ( the object used by tableView:numberOfRowsInSection: )
[dataArray removeObjectAtIndex:indexPath.row];
// tell the table view to delete the row
[tableView deleteRowsAtIndexPaths:indexPath
withRowAnimation:UITableViewRowAnimationRight];
// tell the table view that you're done
[tableView endUpdates];
( According to this link , you should avoid NSInternalInconsistencyException. )
When you add or delete a row you must update your datasource to keep consistency. It seems that your datasource is not updated after deleting the row. To help you it will be useful your datasource methods and the code you use to delete the row.
Your log means that 4-1 = 3, not 4.
You have to take into consideration your deleted rows when returning their count in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
You should have a variable or array containing your number of rows, e.g.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.cellsCount;
}
// somewhere else
[tableView beginUpdates];
self.cellsCount--; // here is an important line of code
[tableView deleteRowsAtIndexPaths:indexPath withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];

how to properly update datasource when inserting and deleting rows from UITableView?

I am trying to delete some rows from UITableView and here is my code...
[self.responsesTableView beginUpdates];
[self.responsesTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:self.processingIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self. responsesTableView endUpdates];
noOfRsponses --;
if (self.segFrndEveryone.selectedSegmentIndex == 0) {
[self.arrFriendComments removeObjectAtIndex:self.processingIndexPath.row];
}else {
[self.arrAllComments removeObjectAtIndex:self.processingIndexPath.row];
}
where one of the two arrays is my datasource depnding on the segment selected.
I am getting the following error and not sure how to deal with this.
The number of rows contained in an existing section after the update
(9) must be equal to the number of rows contained in that section
before the update (9), plus or minus the number of rows inserted or
deleted from that section (0 inserted, 1 deleted) and plus or minus
the number of rows moved into or out of that section (0 moved in, 0
moved out).'
You should update your data source before making manual changes to the UITableView.
// update the data source for the table change
noOfRsponses--;
NSMutableArray *targetArray = (self.segFrndEveryone.selectedSegmentIndex == 0) ? self.arrFriendComments : self.arrAllComments;
[targetArray removeObjectAtIndex:self.processingIndexPath.row];
// update the table view itself
[[self responsesTableView] beginUpdates];
[[self responsesTableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:self.processingIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[[self responsesTableView] endUpdates];
Are you calling the removeObjectAtIndex on the correct array? Based on the error message, you haven't actually removed an object from the datasource that the tableview is expecting you to have removed from. I'm guessing that maybe you are removing from the wrong array.
And one other thing to try: remove the object first and then do the deleteRowsAtIndexPath.
You should use methods for sections
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

How can I add/remove a cell from grouped section uitableview?

How can I programmatically add or remove a cell from a grouped section?
I created a grouped tableview using static cells in storyboard. Inside the storyboard I set the number of rows using the Attribute Inspector panel. For example, for section 1, I define 3 rows. Then using an NSMutableArray of 3 items, I can properly load values into each section correctly at startup.
I ultimately want the ability to add/remove a cell at runtime. That part hasn't been coded yet but to simulate adding a new cell scenario, I added a new item to the array in the code but did not increase the row count for the section in the Attribute Inspector panel. I had hoped that I would not need to make any other changes to accomodate the new item since inside the numberOfRowsInSection method, I'm returning the count of the array for the specific section.
This is the error message that I get when I re-ran the code:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
Apparently I need to somehow specify an additional row count. Can anyone shed some light on how I can do this at runtime? Thanks.
You should not do it through attribute inspector. it abstains you to do dynamic insertion and deletion of cells.
try
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [yourArray count];
}
else do this.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(section==0){
return 3;
}else if(section==1){
return 4;
}
return 0;
}
and so on for different section if u have many section..
you can reload the whole table when you array from which data is read is updated..
[tableView reloadData];
but a better way to do it is to insert row or multiple rows like this in a block.
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:yourIndexPath withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];
you can also add animation to add cell from right or lect or top or bottom.
I hope this helps you!!
Cheers!!
I guess that you hardcoded the number of rows for your section. Because looking at the error it seems that your section is expecting 4 object but your data source contains only 3.
Inside your :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
you should return something like [myArray count], so adding or delting rows shouldn't be a problem if you add or remove the object from your array.
You have Predefined methods in UITableview for Inserting and deleting row, For insertion we can user insertRowAtIndexPath method and for deletion use deleteRowAtIndexPath methods.

UITableView - Remove last cell when there are a certain amount of cells above it

In my UITableView, I have a dedicated cell with an insert control at the bottom to allow the user to insert new rows.
What I want to do is remove/hide this cell when there are a certain number of cells above it (8 in this case).
Here's what I have so far:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 1) {
if ([sites count] == [[BrowserController sharedBrowserController] maximumTabs]) {
return [sites count];
} else {
return [sites count] + 1;
}
} else {
return 1;
}
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
...
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
NSString *newSiteAddress = [NSString stringWithString:#"http://"];
[sites addObject:newSiteAddress];
if ([sites count] == [[%c(BrowserController) sharedBrowserController] maximumTabs]) {
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
[[(BookmarkTextEntryTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] textField] becomeFirstResponder];
}
}
Which causes the following exception to be thrown:
2/01/12 4:28:07.956 PM MobileSafari: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (8) must be equal to the number of rows contained in that section before the update (8), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(0x2bc0052 0x2d51d0a 0x2b68a78 0x1cf2db 0x747518 0x75282a 0x7528a5 0x812481c 0x75e7bb 0x8b2d30 0x2bc1ec9 0x6c65c2 0x6c655a 0x76bb76 0x76c03f 0x76b2fe 0x984a2a 0x2b949ce 0x2b2b670 0x2af74f6 0x2af6db4 0x2af6ccb 0x491879 0x49193e 0x6c3a9b 0x4430 0x2db5)
Here's a relevant paragraph from Apple's UITableView documentation which has to do with inserting and deleting cells:
Clicking on the insertion or deletion control causes the data source
to receive a tableView:commitEditingStyle:forRowAtIndexPath: message.
You commit a deletion or insertion by calling
deleteRowsAtIndexPaths:withRowAnimation: or
insertRowsAtIndexPaths:withRowAnimation:, as appropriate. Also in
editing mode, if a table-view cell has its showsReorderControl
property set to YES, the data source receives a
tableView:moveRowAtIndexPath:toIndexPath: message. The data source can
selectively remove the reordering control for cells by implementing
tableView:canMoveRowAtIndexPath:.
You should create new methods called "insertLastCell" and "deleteLastCell" (or something along those lines) which explicitly tells your table view to insert and delete that last cell via insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation:.
Once the insert and deletes are "committed", only then can you report back different numbers in your numberOfRowsInSection method.

UITableView Deleteing row error

I am a newbie to iPhone app development. So please go easy with me :)
I was trying to implement delete row from UItableView when i get this error, which i am not able understand why
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (6) must be equal to the number of rows contained in that section before the update (4), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'
Here is my code to delete item method
-(void)deleteItem:(NSIndexPath *)path{
Item *i = (Item *)[list objectAtIndex:path.row];
NSLog(#"Deleting item [%#]", i.iName);
int ret;
const char *sql = "delete from items where id = ?;";
if (!deleteStmt)
{ // build update statement
if ((ret=sqlite3_prepare_v2(db, sql, -1, &deleteStmt, NULL))!=SQLITE_OK)
{
NSAssert1(0, #"Error building statement to delete items [%s]", sqlite3_errmsg(db));
}
}
// bind values to statement
NSInteger n = i.iId;
sqlite3_bind_int(deleteStmt, 1, n);
// now execute sql statement
if ((ret=sqlite3_step(deleteStmt)) != SQLITE_DONE)
{
NSAssert1(0, #"Error deleting item [%s]", sqlite3_errmsg(db));
}
// now reset bound statement to original state
sqlite3_reset(deleteStmt);
[list removeObjectAtIndex:path.row]; // remove from table
[self readTable]; // refresh array
}
and this is the commitediting style of the UITableView
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[appDelegate deleteItem:indexPath];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
Can someone please tell me what i am doing wrong. From what i understand the number of rows in the section is not updated. Am i right ??
Thanks in advance.
As stated in the Apple's Table View Programming Guide for iOS the deletion order is relevant:
first delete the item from the table;
second delete it from the model.
So you have to switch the two delete commands:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[appDelegate deleteItem:indexPath];
In my modest opinion and after trying to the same thing, looks like the table still believes the number of rows didn't change, so I make the row hidden and looks like it worked for me.
After some re-looking at the code, figured out the solution myself. The problem was with the the
readTable()
where the older array was not emptied before reading it again. I used the
[list removeAllObjects]
method to empty it. It worked finally. :)
I don't see a [table reloadData]; does it work? Usually it is required.