Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of the "no index path for table cell being reused" message in iOS 6/7?

Since starting to compile my app with iOS 6 (and since also iOS 7) I've started seeing this message. I know that the way that UITableViews go about managing cells is different in iOS 6 but I haven't needed to modify my code for it to keep working. But I'm concerned this message may point to some potential issue that I'm not yet seeing. Can anyone shed any light?

like image 299
Nathan Brown Avatar asked Oct 07 '12 19:10

Nathan Brown


3 Answers

I started to get this error showing up in the log from iOS 7 beta 5 onwards, including in the iOS 7 GM/Release build, whilst never having had it happen in my app in iOS 6 or the earlier iOS 7 betas. After a lot of experimenting I found the cause:

I was using UITableViewCell objects for my section header views and returning them in tableView:viewForHeaderInSection:. This appears to be common practice, especially since iOS 5 when it became easy to design a section header view as a prototype table view cell in a StoryBoard with Interface Builder.

When I changed my app to use just regular UIView subclasses for my section header views, the errors went away and, more importantly, my table view stopped randomly deleting section headers!

It would appear that (since iOS 7 beta 5) UITableView is internally maintaining a mapping of all the UITableViewCell objects in its view hierarchy and their respective index paths. Since a section header (or a table view header of footer) doesn't have an index path, if you use a UITableViewCell object for these views, the table view will get confused when it finds a UITableViewCell for which it doesn't have an index path, resulting in the "no index path for table cell being reused" error and, if you're unlucky, display glitches in your table view:

UPDATE: if you have access to the Apple Dev Forums, here's the thread about it (which I started): https://devforums.apple.com/message/882042#882042

As suggested in that thread, if you don't want to re-factor much, you can create a UIView wrapper around your UITableViewCell and return that as the section header view.

UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
[view addSubview:cell];

return view;

Note however that this "wrapper" UIView approach will not play well with AutoLayout and device rotation, so I suggest that you use a UIView subclass for header and footer cells, not a UITableViewCell subclass as explained in the main part of the answer.

like image 185
mluisbrown Avatar answered Nov 18 '22 07:11

mluisbrown


I'd return the contentView of the UITableViewCell instead of creating a wrapper.. having constraint-jabble fixed in storybord in mind

return cell.contentView;
like image 41
mar-schmidt Avatar answered Nov 18 '22 06:11

mar-schmidt


I had the same problem and it took me few hours to hunt down the issue. Turns out I was calling [textField becomeFirstResponder] while setting up cells (here the textField was part of a custom tableviewcell); [textField becomeFirstResponder]in turns posts keyboardWillShow notification which in turn caused the tableview to prematurely load itself thus causing the infamous "no index path for table cell being reused” message. Once I removed that call, problem disappeared.

like image 26
mpprdev Avatar answered Nov 18 '22 08:11

mpprdev