"unable to dequeue a cell with identifier" only on iPadOS 15.0

I have a UITableView based up. It is running fine on all iOS versions including 15.0. It is also running fine on all iPadOS versions up to 14.x. But only on iPadOS 15.0 it crashes with the following error message:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier TextCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

Is this a know issue? How can I debug it to figure out where the problem lies?

Note that I actually do register the NIB as follows in viewDidLoad:

static NSString *reuseIdentifierTextCell = @"TextCell";

[self.tableView registerNib:[UINib nibWithNibName:@"ChatTextCellCondensed" bundle:nil] forCellReuseIdentifier:reuseIdentifierTextCell];

It is crashing at this line in cellForRowAtIndexPath:

cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifierTextCell forIndexPath:indexPath];

Thanks!

  • Just an idea: have you checked the name of Nib is the exact one ? But if it works on iOS and not iPadOS 15 exclusively, that's unlikely the problem. Have you created different targets for iOS and iPadOS ? If so, maybe the cell is not referenced in the iPad target ? Did you file a bug report ?

Add a Comment

Replies

The app is a universal app with just one target.

I did open a code level technical support request for this issue.

I can work around it with this crazy piece of code:

@try {
  cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifierTextCell forIndexPath:indexPath];
} @catch(id exception) {
  NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"ChatTextCellCondensed" owner:self options:nil];
  cell = [topLevelObjects objectAtIndex:0];
}

Looking at your solution, seems it needs to find in mainBundle.

Did you try:

[self.tableView registerNib:[UINib nibWithNibName:@"ChatTextCellCondensed" bundle: [[NSBundle mainBundle]]     // I'm not sure of the objC syntax, but that's the idea
forCellReuseIdentifier:reuseIdentifierTextCell];
  • Thanks for the input, it didn't help unfortunately. I should probably also mention that on the initial load of the cells it is working fine even on iPadOS 15.0. But then when a reload gets triggered due to another view becoming active the crash happens.

Add a Comment

Same issue here. Since I updated my iPad to iOS 15, developing with it became very confusing and sometimes impossible like right now. Did you receive code level support and found a solution?

Unfortunately there was no solution, I'm still running with the try/catch workaround as shown above.

I had a UITableViewController that had some cells registered in the Storyboard. These cells did not cause any problems. But it also contained other cells that I designed with a separate UINib, so I had to register them specifically in viewDidLoad, like so:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib(nibName: "SCSocialCell", bundle: nil), forCellReuseIdentifier: "SCSocialCell")
    ...
}

The problem appears to be that these manually registered cells are not really registered before the table starts to load data (which happens automatically in a UITableViewController). In other words numberOfSections and numberOfRowsInSection are called even before viewDidLoad is called (or finished, not sure).

I solved it by introducing a bool variable allTableViewCellsRegistered, like so:


private var allTableViewCellsRegistered = false

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib(nibName: "SCSocialCell", bundle: nil), forCellReuseIdentifier: "SCSocialCell")
    ...
    allTableViewCellsRegistered = true
    tableView.reloadData()
}

And adding guard statements in numberOfSections and numberOfRowsInSection like so:

override func numberOfSections(in tableView: UITableView) -> Int {
    guard allTableViewCellsRegistered else {
        return 0
    }
    // rest of code
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard allTableViewCellsRegistered else {
        return 0
    }
    // rest of code
}

Perhaps only adding this in numberOfSections would do, but I added it in both and it's working now.

I believe this problem only surfaced on the iPad, because the cells in question were at the bottom of my tableView. On iPhone, these last/bottom cells dropped off the screen, so cellForRowAt was not yet called for them on initial load. But by the time the user started scrolling to the bottom, viewDidLoad was finished and the cells were registered. So that's why iPhone didn't give me any problems.

Hope this helps someone.