NSInternalInconsistencyException: no section at index 4 - iphone

Hi I have a simple database app on the iPhone that uses core data. I was just looking at some Flurry exception reports and I'm seeing the following error:
NSInternalInconsistencyException: no section at index 4
The number varies in the reports, but it is always the same message. Any idea on what this means and where to start my debugging efforts?

It probably means that you have a tableview which is asking for a non existent section. Most likely, you are returning incorrect values from numberOfSectionsInTableView: for some reason.

Old question, but it's the top hit on Google - so here's a slightly more concise answer:
I've had this error message appear when an incorrect value is passed into NSFetchedResultsController's objectAtIndexPath:
You pass in a NSIndexPath object, which probably has a section index which is beyond the value that you returned from numberOfSectionsInTableView:

try to use
NSIndexPath *path = [NSIndexPath indexPathForItem:item inSection:0];
instead of
NSIndexPath *path = [NSIndexPath indexPathWithIndex:item];

Related

ios - NSLog showing that detailedView is not displayed in the right order

I am trying to pass data from one ViewController to another using storyboard.
Please note this log message:
2012-11-13 22:25:41.711 Modern Notes[8991:15d03] DetailView - (null)
2012-11-13 22:25:41.714 Modern Notes[8991:15d03] MainView - {
CurrentDate = "2012-11-13 05:12:46 +0000";
NoteInString = "This is the first note. It will appear here while testing the app.";
}
You will see that DetailView - has nothing and that MainView show the contents off an array.
The Array is passed on from the MainView. Now both log Messages are generated by this line:
NSLog(#"DetailView - %#", _notedict);
and
NSLog(#"MainView - %#", noteDetailViewControler.notedict);
Where notedict is the Dictionary that holds the information. As you can see (i think) in theory both Log messages should display this array right??
Now it seems strange to me that DetailView is being shown in the Log before MainView where I think it should be the other way around??
Cheers for any tips and happy to provide any details if needed.
EDIT:
ok, so this is where I am sorting my details out:
in the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
I have a line
noteDetailViewControler.notedict = [_listNotes objectAtIndex:indexPath.row];
Now I think my problem is that this line is only set locally and is not carried over to another viewcontroller - am I right??
Obviously _notedict is not yet set, or already removed again, when you log it in the DetailView. You need to show us, when (in which method) you initalize the data, when you log it and when you show the mainView / detailView. We can not not help anymore with the information given right now.

UITableView occasional crash while appending rows

My app has a UITableViewController that is getting an "Invalid Update: invalid number of rows in section 0..." after appending rows. Thing is, it happens only in %0.2 of sessions. Our app, has millions of sessions so the crashes are adding up.
The flow is simple. It's part of a feature that matches a user's music with our catalog of videos. A background thread makes a series of requests. A request goes out, response comes back with results, then those results get appended to a tableView within one of our tabs. The requests go in batches and can add up to lots of resulting rows. So rather than call reloadData after a batch comes in, I wanted to append them properly. Works awesome, but occasionally crashes.
I was able to reproduce this one time on a device. It has never happened on simulator. As far as I know, the crash is reasonably random, although it mostly happens on 3gs. The fewest # of crashes come from 4s.
Here's the code. A response comes back. In this case, allMatches is every match so far (the data source for the table). batchMatches is the number of new artists. Both are arrays:
[self.tableView beginUpdates];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (int i = [allMatches count] - [batchMatches count]; i < [allMatches count]; ++i) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[paths addObject: indexPath];
}
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
[paths release];
Code is pretty simple. It just appends rows to the end, one for each result. Never deletes. An example of full exception message is "Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (131) must be equal to the number of rows contained in that section before the update (131), plus or minus the number of rows inserted or deleted from that section (20 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)." Numbers are all over the place in actual crash reports, so it's not a specific batch number.
Like I said, it almost always works. And it crashes usually on 3GS. I'm wondering if this could possibly be a framework bug. I could always call reloadData after each batch returns but it results in ugly flashing of table cells each time. On purpose I triggered the exception and it seems after that the table is dead, so I couldn't do a try/catch with a reloadData as a fallback in the catch block.
Can anyone out there shed some light? Apologies for length of this post.
EDIT: The server requests are done using NSOperationQueue, so they are on a background thread. When the response returns, I post a notification on the main thread, which causes the table code to run. The notification is posted like this:
NSNotification *notification = [NSNotification notificationWithName:notificationName object:self];
[self performSelectorOnMainThread:#selector(postNotification:) withObject:notification waitUntilDone:NO];
Post notificiation is simply a wrapper around [[NSNotificationCenter defaultCenter] postNotification:notification]. So the table code should be on the main thread.
My guess is, you are executing the table view update in a background thread. You should do that on the main thread instead.
Place your code inside a dispatch_async block.
dispatch_async(dispatch_get_main_queue(), ^(void) {
// ..
});

NSFetchresultsController crashes on deletion of dependent objects

I'm using the NSFetchResultsControlleDelegate Methods from this awesome Post:
http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html
However:
I have the special situation that the objects in my tableview are connected to each other.
So: if I delete an object, I get 2 events in the callback: on for the NSFetchedResultsChangeDelete and one NSFetchedResultsChangeUpdate.
The method crashes in the NSFetchedResultsChangeDelete branch due to a invalid indexPath.
I looked at it for a while and though of some workarounds for this but did not yet come up with a clean solution to that case.
Any hints ?
thanks in advance
If the deleted object is the only object in it's table view section, the section of other objects will change. A section change will cause the indexPath to be changed as well. If you still try to access the object using the old indexPath, the app will crash.
To work around that, use the newIndexPath method parameter if it's available:
NSIndexPath* ip = nil;
if (newIndexPath != nil) {
ip = newIndexPath;
} else {
ip = indexPath;
}
NSManagedObject *changedObject = [controller objectAtIndexPath:ip];
Hope that helps.
Cheers,
Christian

Why are multiple touches causing my iPhone app to crash?

In my app, I am getting the row index as the user taps on the row or selected row. But if a row is tapped twice, my app crashes.
What could be causing this behavior, and how can I fix it? Here's the code I'm using:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
abc *xyz = [[abc alloc] init];
dcs = [allHadits objectAtIndex:indexPath.row];
hk = dcs.kokid;
[dcs release];
}
Do you mean tapping on the same row twice makes it crash? If so, it might be because of the [dcs release]. I don't know what dcs is (unless that's supposed to be xyz) but grabbing a pointer to the object in the array and then calling release on it might be releasing the object in the array, making it crash next time the row is hit. Delete the [dcs release] and see if it still crashes. My memory management isn't the greatest though so I could be wrong.
Don't release dcs. Why are your variables named so poorly?

Is Apple's iPhone SDK 3.0 CoreDataBooks example broken?

I've come across this issue in my application, and have reproduced it using Apple's CoreDataBooks codebase with 0 modifications to the code. The problem is if you make an edit to a managed object, and save the context, with the result being a section with only one row now having no rows, and a new section created with the resulting object added to it, then you get the invalid update exception. It also seems to depend on the ordering of the rows.
To recreate follow these steps:
Open a new instance of CoreDataBooks example
Edit Richard Dawkins book, "The Selfish Gene" and change the author to Ben. Save it. If you return to the main view you'll notice that the book is under a new section named Ben.
Edit this book again, and change the author to Doug. Save it. You'll get the following exception:
2009-10-01 15:14:29.050 CoreDataBooks[10898:20b] *** Assertion failure in -[UITableView_endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-963.10/UITableView.m:729 2009-10-01 15:14:29.051 CoreDataBooks[10898:20b] Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of rows in section 1. 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, 0 deleted). with userInfo (null)
I'd post the code from my own app to make sure I'm not missing any required delegate methods, except as the example above shows it's an issue which affects Apple's CoreDataBooks example straight off the shelf. The NSFetchedResultsController delegate methods are all implemented as per their own examples. Their code doesn't seem to forget to handle newly created sections either, as it works in other cases with different section orderings.
Any help would be appreciated. Example modified code from the CoreDataBooks example would be great.
The way to fix this seems to be to change these lines in the table updates section of the RootViewController:
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;
to:
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
for some reason. The problem seems to come from deleting the last row in a section; it appears that unless you add the extra insertRows, the UITableView freaks out over the fact that the section which has been deleted suddenly gains a whole bunch of extra rows.
Took me hours to figure that one out....
One recommendation is that you completely delete the application from your iPhone and/or reset the Simulator, to ensure that you don't have any remnants of a corrupted data store.
After you delete the app or reset the Simulator, recompile this app from scratch. This will create a fresh copy of the application and, more importantly, a fresh data store.
Re-run your test after doing that, to see if you run into the same problem.