Trying to debug error: *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:]

22,596

Solution 1

Ok, sorry, SNAFU alert.

I'm not sure how this occurred but if you notice in my function declaration for "cellForRowAtIndexPath"... it just has atIndexPath instead of cellForRowAtIndexPath. I must have done some sort of ill advised global search and replace and it wrecked my project.

Working now. Thanks.

Question - why would the code compile without error or warning - Wow - this took way too long to find.

Solution 2

I just ran into the same issue, but I carelessly declared:

<UITableViewDelegate, UITableViewDelegate>

rather than correctly:

<UITableViewDelegate, UITableViewDataSource>

Joe

*update - I have also noticed in xCode 4.3 the template generated when you create a new UITableViewController Class is missing a key item in cellForRowAtIndexPath. That is:

    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}

Solution 3

Based upon UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:, it looks like you might have forgotten to set a cell identifier upon instantiation:

cell = ((DetailCell *)[tableView dequeueReusableCellWithIdentifier:DetailCellIdentifier]);
if (! cell)
{
    // build the cell here
}

If not, where in the code is the error being caused?

Solution 4

In my case, iOS 5.0 ~ 6.0 with storyboard should have same cell identifier between the method

(- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath) and **storyboard file**.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell"; ... }

If you used @"Cell" for cell identifier, should use the name at the Identifier of corresponding tableViewCell in attributes inspector of storyboard file.

When you make a subclass of UITableView file, the default code uses @"Cell", but not storyboard, blank. So need to pay attention.

Share:
22,596
phil
Author by

phil

golf, objective C, golf, computers, golf, golf

Updated on May 28, 2020

Comments

  • phil
    phil about 4 years

    I have a simple UITableviewController that used to work fine and now something has broken it.. It presents a simple form that allows me to add a simple 3-field record to a core-data managed object.

    When I add a record, it should return to the table and display the contents. I can see that it is writing the record to the database but the table is empty and the error below appears. I can keep adding records by clicking on my "Add" button but each time I save the new record and return to the table, it is empty.

    The complete error I see is this..

    *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:5678
    2011-10-01 22:48:11.860 Gradetrack[59617:207] Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath: with userInfo (null)
    

    If I stop the simulator and restart it, I can see from my NSLog statements that it has discovered the right number of records from the database and has tried to load the table but at this point, I get this similar error and the stack trace below.

    2011-10-01 23:08:50.332 Gradetrack[59795:207] >>> Enumber of courses entered thus far: 4 
    2011-10-01 23:08:50.334 Gradetrack[59795:207] *** Assertion failure in -[UITableView _createPreparedCellForGlobalRow:withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m:5678
    2011-10-01 23:08:50.337 Gradetrack[59795:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
    *** Call stack at first throw:
    (
        0   CoreFoundation                      0x00fd05a9 __exceptionPreprocess + 185
        1   libobjc.A.dylib                     0x01124313 objc_exception_throw + 44
        2   CoreFoundation                      0x00f88ef8 +[NSException raise:format:arguments:] + 136
        3   Foundation                          0x000e43bb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116
        4   UIKit                               0x0035ec91 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 883
        5   UIKit                               0x003544cc -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
        6   UIKit                               0x003698cc -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1561
        7   UIKit                               0x0036190c -[UITableView layoutSubviews] + 242
        8   QuartzCore                          0x01f70a5a -[CALayer layoutSublayers] + 181
        9   QuartzCore                          0x01f72ddc CALayerLayoutIfNeeded + 220
        10  QuartzCore                          0x01f180b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
        11  QuartzCore                          0x01f19294 _ZN2CA11Transaction6commitEv + 292
        12  UIKit                               0x002eb9c9 -[UIApplication _reportAppLaunchFinished] + 39
        13  UIKit                               0x002ebe83 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 690
        14  UIKit                               0x002f6617 -[UIApplication handleEvent:withNewEvent:] + 1533
        15  UIKit                               0x002eeabf -[UIApplication sendEvent:] + 71
        16  UIKit                               0x002f3f2e _UIApplicationHandleEvent + 7576
        17  GraphicsServices                    0x01928992 PurpleEventCallback + 1550
        18  CoreFoundation                      0x00fb1944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
        19  CoreFoundation                      0x00f11cf7 __CFRunLoopDoSource1 + 215
        20  CoreFoundation                      0x00f0ef83 __CFRunLoopRun + 979
        21  CoreFoundation                      0x00f0e840 CFRunLoopRunSpecific + 208
        22  CoreFoundation                      0x00f0e761 CFRunLoopRunInMode + 97
        23  UIKit                               0x002eb7d2 -[UIApplication _run] + 623
        24  UIKit                               0x002f7c93 UIApplicationMain + 1160
        25  Gradetrack                          0x00002034 main + 102
        26  Gradetrack                          0x00001fc5 start + 53
    

    Based on NSLog statements, this is the last subroutine executed.

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        // Return the number of rows in the section.
        NSLog(@">>> Enteringg %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);   
    
        id <NSFetchedResultsSectionInfo> sectionInfo = 
        [[_fetchedResultsController sections] objectAtIndex:section];
        NSLog(@">>> Enumber of courses entered thus far: %d ", [sectionInfo numberOfObjects]);  
    
        return [sectionInfo numberOfObjects];
    }
    

    Note: the output from the Number of courses entered thus far... was 4, which was correct.

    Here is where I return cells back to the UITableViewController

    - (UITableViewCell *)tableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath {
        NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    
    
        static NSString *CellIdentifier = @"Cell";
    
        UITableViewCell *cell = 
        [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] 
                     initWithStyle:UITableViewCellStyleSubtitle 
                     reuseIdentifier:CellIdentifier] autorelease];
        }
    
        // Set up the cell...
        [tableView setAllowsSelectionDuringEditing:NO];
        [self configureCell:cell atIndexPath:indexPath];
        // load the cell with an appropriate image
        NSString *path = [[NSBundle mainBundle] pathForResource:@"studentprofile" ofType:@"png"];
        UIImage *theImage = [UIImage imageWithContentsOfFile:path];
        cell.imageView.image = theImage;
    
        return cell;
    }
    

    Based on these errors and my stack trace, can anyone point me in the right direction?

    Many thanks,

    Phil

  • phil
    phil over 12 years
    Thanks. Check it out- I edited the original post to include that bit of code.
  • theLastNightTrain
    theLastNightTrain almost 12 years
    I don't believe you need to allocate a table view cell manually now, because the dequeue call will always give you one back (it will create one if needed).
  • Joe Fratianni
    Joe Fratianni almost 12 years
    If this is true there must be another problem. Without adding this I get a crash. When I add this the program runs fine. Perhaps this is not needed if I use UITableviewcontroller, but otherwise is? I must investigate further.
  • Elise van Looij
    Elise van Looij almost 12 years
    @theLastNightTrain's belief is not correct. From the documentation for dequeueReusableCellWithIdentifier: "Return Value A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue."
  • theLastNightTrain
    theLastNightTrain almost 12 years
    My belief is based on using Storyboards and iOS 5 with a cell template defined in the TableView - you ask for a cell with the identifier and always get one back (assuming the identifier names match :)).
  • Jeff Hay
    Jeff Hay almost 12 years
    If, however, you are not using storyboards, you do indeed need to create the cell if dequeue... returns nil. This fixed the issue I was having as well. Good catch, @JoeFratianni.
  • Scott Lieberman
    Scott Lieberman almost 11 years
    Hi Phil, the code would compile without error or warning because technically you are allowed to create a method with "atIndexPath" rather than "cellForRowAtIndexPath". Obviously, your "atIndexPath" method will never get called by the UITableViewDelegate, but it is totally legal to create your own custom method with that as its name.