When I called [tableView insertRowsAtIndexPaths: withRowAnimation:], crashed in iOS10 - ios

- (void)registerCellCallBack:(id<CellCallBack>)callBack {
int i = 0;
for(; i < _dataSource.count; ++i) {
id<CellCallBack> oldCallBack = _dataSource[i];
if([callBack key] <= [oldCallBack key]) {
break;
}
}
if(i < _dataSource.count) {
[_dataSource insertObject:callBack atIndex:i];
} else {
[_dataSource addObject:callBack];
}
[self.table beginUpdates];
[self.table insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.table endUpdates]; //--crashed here called "NSInternalInconsistencyException(SIGABRT)"
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _dataSource.count;
}
The code which even was well in iOS9, crashed in iOS10, but not appear when I debug my code.
Crash info:
Invalid update: invalid number of rows in section 0. The
number of rows contained in an existing section after the update (7)
must be equal to the number of rows contained in that section before
the update (0), plus or minus the number of rows inserted or deleted
from that section (1 inserted, 0 deleted) and plus or minus the number
of rows moved into or out of that section (0 moved in, 0 moved out).

You need to change as per below:
To
[self.table reloadData];
From
[self.table beginUpdates];
[self.table insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[self.table endUpdates]; //--crashed here called "NSInternalInconsistencyException(SIGABRT)"

Related

iOS - Error when adding row to UITable (Objective-C)

I'm getting this error when adding a row to a UITable.
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 7. The number of rows contained in an existing section after the update (0) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
number of elements:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return mArray[section];
}
return 1; // only top row showing
}
// Return the number of rows in the section.
return 1;
}
Counting number to be in each part:
int k = 0;
for (int i = 0; i < 28; i++) {
if ([[currentEntry objectForKey:#"item"] isEqualToString:items[i]]) {
mArray[i] += 1;
k = i;
}
}
Adding to table
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
NSLog(#"SSection:%d", rows);
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
dispatch_async(dispatch_get_main_queue(), ^{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
});
}
Error occurs here
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
});
}
}
}
}
This error only occurs in one section which is 7. All other sections are fine
First you need add object in collection which telling tableview about count of items for appearing, create index path for new cell and make insert row with index path. Perhaps you create wrong index path.
I think your array and your numberOfRows should be matching in your 7th section.
//MARK: UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 7) {
return YOUR_ARRAY.count;
}
}

NSInternalInconsistencyException while deleting cell from collectionView

I want to delete a cell from a UICollectionView. While deleting cell I get
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (5) must be equal to the number of items contained in that section before the update (5), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).' Error.
Here is my code:
[self.imgArray removeObjectAtIndex:indexForDelete];
[self.collectionView performBatchUpdates:^{
NSIndexPath *indexPath =[NSIndexPath indexPathForItem:indexForDelete inSection:0];
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} completion:^(BOOL finished) {
}];
I am appending one dummy cell when my array count is not 5
Here is code for numberOfItems in numberOfItemsInSection
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if(self.imgArray.count == 5)
{
return self.imgArray.count ;
}
else
{
return self.imgArray.count + 1;
}
}
I found many solution on Google and Stackoverflow but nothing found help full for me.
performBatchUpdates mainly used to perform actions for multiple cells. i.e. delete, insert, move.
Try this,
[self.collectionObj performBatchUpdates:^{
[self.imgArray removeObjectAtIndex:indexForDelete];
NSIndexPath *indexPath =[NSIndexPath indexPathForItem:indexForDelete inSection:0];
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
[self.collectionView reloadData];
} completion:^(BOOL finished) {
}];
You can also try directly for 1 cell delete without using performBatchUpdates
[self.imgArray removeObjectAtIndex:indexForDelete];
NSIndexPath *indexPath =[NSIndexPath indexPathForItem:indexForDelete inSection:0];
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
[self.collectionView reloadData];
Hope, this will help you.
Thanks
I think you may need to separate the update into two stages to avoid the NSInternalInconsistencyException.
#property (assign, nonatomic) BOOL isMyCollectionViewUpdating;
//...
[self.imgArray removeObjectAtIndex:indexForDelete];
[self.collectionView performBatchUpdates:^{
self.isMyCollectionViewUpdating = YES;
NSIndexPath *indexPath =[NSIndexPath indexPathForItem:indexForDelete inSection:0];
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} completion:^(BOOL finished) {
self.isMyCollectionViewUpdating = NO;
[self.collectionView reloadData];
}];
and for the collection view numberOfItemInSection
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if (self.isMyCollectionViewUpdating)
{
return self.imgArray.count;
} else {
if(self.imgArray.count == 5)
{
return self.imgArray.count ;
}
else
{
return self.imgArray.count + 1;
}
}
}

Insertion and deletion of rows in UITableView sometimes causes the crash?

I am doing very usual stuff.
First modifying the data model and then updating the TableView. But sometimes app crashes.
And throws error something like that (depends on insertion or deletion).
Fatal Exception: NSInternalInconsistencyException
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (10) must be equal to the number of rows contained in that section before the update (10), 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).
Here is my insertion code.
[self.tableView beginUpdates];
[self.stories insertObject:story atIndex:0];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
and Deletion code.
[tableview beginUpdates];
[stories removeObject:story];
NSIndexPath *indexpath = [tableview indexPathForCell:cell];
if(indexpath) {
[tableview deleteRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationTop];
}
[tableview endUpdates];
Insertion Code:
[self.stories insertObject:story atIndex:0];
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Deletion Code:
[stories removeObject:story];
[tableview beginUpdates];
NSIndexPath *indexpath = [tableview indexPathForCell:cell];
[tableview deleteRowsAtIndexPaths:#[indexpath] withRowAnimation:UITableViewRowAnimationTop];
[tableview endUpdates];
Note: You should not add/remove object to an array inside updating your tableview's rows.
Either do [tableview reloadData]; or [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
Also you are doing database operation in-between [self.tableView beginUpdates];
and [self.tableView endUpdates];. It's not proper.
As per the error suggests, there is a mismatch in table view rows and data source of that table view.

Deleting all rows from UITableView

I keep running into an assertion failure but I am not sure how to resolve.
Initially I did a proof of concept app to understand how this functions and had this code in it:
if (self.arrNonATIResults.count > 0) {
NSMutableArray* arrIndexPaths = [NSMutableArray array];
for(int i=0; i<[self.arrNonATIResults count]; i++) {
NSIndexPath *anIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
[arrIndexPaths addObject:anIndexPath];
}
[self.accountTable beginUpdates];
[self.accountTable deleteRowsAtIndexPaths:arrIndexPaths withRowAnimation:UITableViewRowAnimationTop];
self.arrNonATIResults = [NSMutableArray array];
[self.accountTable endUpdates];
}
It worked fine. Moving that code into my app I ran into this assertion failure:
Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (0) 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, 2 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).
Here's where I am getting confused, self.arrNonATIResults (the table datasource) contains two objects (it's hardcoded) - so the table has only two rows. Where is the 3rd row in the error message coming from? I did read that if you remove all rows then you also have to remove the section as well. Is that the third item in the error message?
So I rewrote my initial code but this still shouldn't work because the arrIndexPath array is only going to include 2 NSIndexPaths. Can anyone point me in the right direction as to what I am doing wrong?
- (void) clearNonATITable {
if (self.arrNonATIResults.count > 0) {
NSMutableArray* arrIndexPaths = [NSMutableArray array];
for(int i=0; i<[self.arrNonATIResults count]; i++) {
NSIndexPath *anIndexPath = [NSIndexPath indexPathForRow:i inSection:0];
[arrIndexPaths addObject:anIndexPath];
}
[self.accountTable beginUpdates];
for (int i=0; i<arrIndexPaths.count; i++) {
NSIndexPath* thisIndexPath = [arrIndexPaths objectAtIndex:i];
if (self.arrNonATIResults.count > 0) {
[self.accountTable deleteRowsAtIndexPaths:[NSArray arrayWithObjects:thisIndexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
[self.arrNonATIResults removeObjectAtIndex:0];
} else {
NSIndexSet* setIndexSections = [[NSIndexSet alloc] initWithIndex:thisIndexPath];
[self.accountTable deleteSections:setIndexSections withRowAnimation:UITableViewRowAnimationFade];
}
}
[self.accountTable endUpdates];
}
}
[myArray removeAllObjects];
[tableView reloadData];
The issue was the app was using 3 datasources for this one tableview - the datasource would change based on a segment control selection. I just needed to determine which source it was and use it's count for the number of NSIndexPaths to remove.

Adding a row to a tableView not working

I have a custom UITableView I'm trying to add a row to the tableView. Here is my code:
- (IBAction)addRow:(id)sender
{
NSInteger indexPath = [self.rowArray count] - 1;
// I'm adding an object to an array of all the cell ids I have.
[self.rowArray insertObject:#"rowSix" atIndex:indexPath]; // rowSix is a cell ID
[self.myTableView beginUpdates];
[self.myTableView endUpdates];
}
This is the error that it outputs:
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 (8) must be equal to the number of rows contained in that section before the update (7), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Update
In cellForRowAtIndexPath:
NSString *cellID = [self.rowArray objectAtIndex:[indexPath row]];
customCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
Try this one-
//Update data source with the object that you need to add
[tableDataSource addObject:newObject];
NSInteger row = //specify a row where you need to add new row
NSInteger section = //specify the section where the new row to be added,
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationRight];
[self.tableView endUpdates];
try this -
- (IBAction)addRow:(id)sender
{
[self.rowArray addObject:#"New Item"];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:[self.rowArray count] inSection:0];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}

Resources