exception while deleting a cell - iphone

I have given 2 colours to my cell.
cell.contentView.backgroundColor = indexPath.row % 2 ? [UIColor whiteColor] : [UIColor blackColor] ;
Now, when i delete a row, say i deleted the cell that contains the colour black, then there will be 2 rows that contains the colour white. So i tried refreshing the row;
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
This works, but when i delete all the records i get the following exception; Why is this ?
Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:961 and
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. Attempt to delete more rows than exist in section.'
my code;
[self.tableView beginUpdates];
[self.myArray removeObjectsInArray:discardedItems ];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self.tableView endUpdates];
How can i solve this ?

It thinks you have more rows than you do. Try something like this...
[self.tableView beginUpdates];
[self.myArray removeObjectsInArray:discardedItems ];
[self.tableView reloadData];
[self.tableView endUpdates];
Due to the nature of the tableview's data delegate, once you modify your data model the rest should follow.

Ok, let's think that you have 6 objects in your array, each one corresponding to the data-source for each cell. So, the delegate methods are called and you can actually edit the row and remove it, so you will end up now with 5 objects. What I always do and works like a charm is first re-sizing the array with the data-source and then updating the view.
//Remove the data
[self.myArray removeObjectsInArray:discardedItems ];
//Update the view
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self.tableView endUpdates];
Unless you need to reload the data, meaning that some of the data-sources changed, you probably shouldn't be calling the update method. The exception was probably coming because you were trying to get info out of the sixth element of the array before you even finished updating the UITableView.
Hopefully this will work.

Related

Removing a cell from the tableView

I have a tableview added to a viewController (I wanted it this way).
Each cell of the tableview has a segmentcontroller, when the user clicks on it the cell deletes/removes.
I end up getting an exception, and i have no clue how to solve it.
2012-01-23 15:35:26.729 TestProject [21003:707] * Assertion failure
in -[UITableView _endCellAnimationsWithContext:],
/SourceCache/UIKit/UIKit-1448.89/UITableView.m:995
2012-01-23 15:35:26.761 TestProject [21003:707] * 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 (2) must be
equal to the number of rows contained in that section before the
update (2), plus or minus the number of rows inserted or deleted from
that section (0 inserted, 1 deleted).'
My code so far;
in the button event;
UITableViewCell *cell=(UITableViewCell *)segmentController.superview.superview;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
Person *person= [[self allThdata] objectAtIndex:indexPath.row];
[self.allThdata removeObjectIdenticalTo:person];
[self.myTableView beginUpdates];
[self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self.myTableView endUpdates];
I have also tried removeObjectAtIndex: indexPath.row and removeObject: person . None of this worked
Call to removeObjectAtIndex: should be inside beginUpdates block.
This should do the trick:
UITableViewCell *cell=(UITableViewCell *)segmentController.superview.superview;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
[self.myTableView beginUpdates];
[[self allThdata] removeObjectAtIndex:indexPath.row];
[self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:YES];
[self.myTableView endUpdates];

Adding a cell in UITableView with animation

I have a UITableView. I'm population it from a NSDictionary with arrays for each set of items on the table: labels, footers, Headers, UIViews, etc.
In section 0, I want a row #2 appear when a switch in row #1 is switched to on.
What I have done and it works is, in numberOfRowsInSection I added this code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (interruptor.isOn==NO && section==0) {
return [[[infoTableContentArray objectAtIndex: section] objectForKey:kLabelKey] count]-1;
}else{
return [[[infoTableContentArray objectAtIndex: section] objectForKey:kLabelKey] count];
}
}
and the action linked to the switch (interruptor) is:
-(IBAction)accioInterruptor:(id)sender{
[infoAndSettingsTable reloadData];
}
so when the switch is switched, the table reloads and the cell appears or disappears.
it actually works, but there is no animation, which makes it, mhh... well, you know.
I've tried to implement the reloadRowsAtIndexPaths:withRowAnimation, adding it to the code called by the switch:
-(IBAction)accioInterruptor:(id)sender{
[infoAndSettingsTable beginUpdates];
[infoAndSettingsTable reloadRowsAtIndexPaths:[[infoTableContentArray objectAtIndex: 0] objectForKey:kLabelKey] withRowAnimation:UITableViewRowAnimationBottom];
[infoAndSettingsTable endUpdates];
}
But, it dowsn't work. It crashed on the line [infoAndSettingsTable endsUpdates];
BTW, in all the cases the following:
[[infoTableContentArray objectAtIndex: 0]
is the array which contains the labels for that section.
Am I doing it right or I'm Epic-Failing alltogether?
Thanks in advance!
simple way to do this......
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:deleteIndexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
insertIndexPaths is an array of NSIndexPaths to be inserted to your table.
deleteIndexPaths is a array of NSIndexPaths to be deleted from your table.
Example array format for index paths :
NSArray *insertIndexPaths = [[NSArray alloc] initWithObjects:
[NSIndexPath indexPathForRow:0 inSection:0],
[NSIndexPath indexPathForRow:1 inSection:0],
[NSIndexPath indexPathForRow:2 inSection:0],
nil];
got it from this question
the argument to reloadRowsAtIndexPaths: should be an array of NSIndexPath objects identifying the rows you want to reload, not the labels for that section. Also, looks like you want to reload a section so I would try the following:
-(IBAction)accioInterruptor:(id)sender {
[self reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationBottom];
}
Why don't you just use UITableView's insertRowsAtIndexPaths:withRowAnimation:? It has been built exactly for this purpose, the UITableView class reference has the exact description and usage examples.
Apart from being cleaner it is also more performant since you don't have to reload the entire table (only really matters if you have lots of cells in it though)

Error : Number of Rows In Section in UITableView in iPhone SDK

I am getting this error while I am trying to load the data into my table view.
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 (73) must be equal to the number of rows contained in that section before the update (71), plus or minus the number of rows inserted or deleted from that section (3 inserted, 0 deleted).
What could be wrong?
Thanks
EDIT :
I am initializing the array on ViewWillAppear and adding new objects to the same array on Tableview's didSelectRowAtIndexPath method
Here is the code On viewWillAppear :
cellTextArray = [[NSMutableArray alloc] init];
[cellTextArray addObjectsFromArray:newPosts];
Here is the code which modifies the array on didSelectRowAtIndexPath :
[cellTextArray addObjectsFromArray:newPosts];
NSMutableArray *insertIndexPaths = [NSMutableArray array];
for (NSUInteger item = count; item < count + newCount; item++) {
[insertIndexPaths addObject:[NSIndexPath indexPathForRow:item
inSection:0]];
}
[self.table beginUpdates];
[self.table insertRowsAtIndexPaths:insertIndexPaths
withRowAnimation:UITableViewRowAnimationFade];
[self.table endUpdates];
[self.table scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionNone
animated:YES];
NSIndexPath *selected = [self.table indexPathForSelectedRow];
if (selected) {
[self.table deselectRowAtIndexPath:selected animated:YES];
}
Here newPosts is an array which has the values that are added to cellTextArray on
didSelectRowAtIndexPath method and viewWillAppear method.
If you have updated the array of data after initialization then you can call this method [yourTable reloadData].
And, it be better if you post the codes here. Then may be some one can help you quickly.
I think, the problem is with the statement in the didSelectRowAtIndexPath method.
You have added the following statement
[self.table insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationFade];
This statement adds the new rows to the table. but the number of rows in the datasource array for that section is different with the number of rows in that section of that table.
So the App is terminated.
Please try by removing the above statement and add required data to the dataSource Array at required indexes and reload the table
Regards,
Satya

How to refresh a UITableViewController or NSFetchedResultsController?

I have a little problem with my UITableViewController or NSFetchedResultsController. I am not sure which is the problem soure but I guess its the UITableViewController.
As I said I use a NSFetchedResultsController to fill my data into a UITableViewController. The data is sorted by date and is also displayed in sections by date-year, e.g. May 2010/June 2010/ and so on. This is displayed as the section header.
Now when I add new data, it automatically uses the current date as default, but if I want to use a date, that is currently not in the section list, e.g. April 2010 (currently May and June in the list), then this is not displayed correctly. Only when I quit the app and start it again it will show the new section headers and everything is fine.
So I somehow need to be able to refresh my list or update it. By just adding it to the context and changing it does not seem to update it.
Again, I am not sure what I need to update, if it is my NSFetchedResultsController object or the UITableViewController.
UPDATE #1:
I just figured that there is an exception in this method :
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
This is where I move the data :
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch(type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
// [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
// Reloading the section inserts a new row and ensures that titles are updated appropriately.
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
This method is pretty much taken from the CoreDataBooks example from Apple. And this is the error :
Serious application error. An
exception was caught from the delegate
of NSFetchedResultsController during a
call to -controllerDidChangeContent:.
*** -[NSMutableArray removeObjectAtIndex:]: index 1 beyond
bounds [0 .. 0] with userInfo (null)
And after that, the edit mode (where the delete button appears) does not work anymore.
Thanks.
Ok, looks like I found a solution, I just skip these
[self.tableView beginUpdates];
[self.tableView endUpdates];
and always do this.
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView reloadData];
}
I will obviously give this some more logic, since the problem only occures when I want to move my data in a section that does not exist before. Until someone can give me a real solution, I will go with this one.
Adopting the fix by Apple in iPhoneCoreDataRecipes in version 1.2, the proper thing to do is to replace
// Reloading the section inserts a new row and ensures that titles are updated appropriately.
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
with
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
(FileMerge is your friend!)
Note, there's another fix in version 1.2 that prevents erratic crashing when creating new entries. I had reported this and it was fixed within two weeks. I encourage you to file bug reports with Apple. They're far more responsive than you think, and you can expect to get the best possible fix.
You need to implement the controller:didChangeSection:atIndex:forChangeType: delegate methods. In it, send insertSections:withRowAnimation:, deleteSections:withRowAnimation:, and reloadSections:withRowAnimation: messages to your table view depending on the reported change type.

UITableView is getting interaction when changing rows with animation

I have a tableview on a nib file with the interaction setting turned off. I'm animating a section change like this:
[myTableView beginUpdates];
[myTableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[myTableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES];
[myTableView endUpdates];
The problem is that, when I do this, the rows become selectable. How do I keep the interaction disabled while keeping the animation?
use this
self.tableView.userInteractionEnabled=NO;