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?
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.
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"SectionHeader" owner:self options:nil]; SectionHeaderView *sectionHeaderView = nib[0];
You can't create a standalone view in a StoryBoard which isn't a view controller as far as I know. –
Prophesy UIView
with the same frame and then add your UITableViewCell
object as a subview, so creating a UIView
wrapper for the section header cell. –
Prophesy contentView
is that all the targets/delegates on the cell will stop working. So only do this if you have static content –
Vicarious UITableViewCell
for a header or footer view then that's your problem. Try using just a regular UIView
subclass. –
Prophesy I'd return the contentView of the UITableViewCell instead of creating a wrapper.. having constraint-jabble fixed in storybord in mind
return cell.contentView;
UIView
subclass as a header / footer cell not a UITableViewCell
subclass. This will always work, even with AutoLayout (@BartvanKuik). The UIView
wrapper solution is a quick fix alternative. –
Prophesy UITableViewCell
view
, apply it to the contentView
and it should appear correctly, at least that was the easy fix for me. This answer is a much easier fix if you've already wired your section headers up as cells in a storyboard. –
Prickett 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.
dispatch_async(dispatch_get_main_queue(), { self.textField.becomeFirstResponder() })
and the problem disappeared –
Pattypatulous Addition to the accepted answer (mluisbrown), I needed to add an autoresizingMask to the header cell, since mine contained a multi-line label, i.e.
UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
cell.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[view addSubview:cell];
return view;
UIView
wrapper, it would be better to make your header / footer cells UIView
subclasses, not UITableView
subclasses. That way you wouldn't have to add an autoresizing mask. –
Prophesy This is an internal UIKit bug - as mentioned in Apple's own dev forums. It's supposedly fixed in newer versions of xcode, although I wasn't able to find info regarding which version fixes this.
As an addition to my previous post (in which I mentioned that this was apparently a bug with UIKit), I was able to find a workaround for my particular case (in which the message was related to some strange visualisation glitches on the table).
Apparently my custom cell's overridden -(void)setEditing:animated:
was taking too long to return.
My previous code was:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self someAdditionalCode];
}
I was able to fix it by changing it to:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
// DRM: we want to perform the actions from this block in the main thread, but
// asynchronously to avoid excessive delays which were causing issues.
//
dispatch_async(dispatch_get_main_queue(), ^void()
{
[self someAdditionalCode];
});
}
I had the same problem with the error message appearing. As far as I can see it is caused by reloading the table view from a function called by the the textfield as part of its delegate protocol. Ie textFieldDidEndEditing -> [controller.tableview reload...]
Doing my endupdates after resignfirstresponder solved my problem (Have a UITextFIeld in my custom cell)
-(void)textfieldEditDone
{
....
[textField resignFirstResponder];
[self.tableView endUpdates];
For the record, I encountered this message too when running under iOS 6. It appears that some code either inherited or imported had something like this:
(NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
if ([delegate respondsToSelector:@selector(numberOfItemsInSection:)]) {
rows = [delegate numberOfItemsInSection:section];
[tableView beginUpdates];
[tableView endUpdates];
}
}
When the beginUpdate: / endUpdate: sequence was removed, the problem magically disappeared.
This is obviously an old question, but hopefully this can help anyone who still gets this issue in iOS8+ because this is still the top question that comes up for this particular error message.
I was using PINRemoteImage to async download an image to a UIImageView that was inside a custom UITableViewCell.
In order to resize the row properly (dynamic height cells using auto-layout) once the image had loaded, I called:
self.tableView beginUpdates;
self.tableView endUpdates;
I was then getting the "no index path for table cell being reused" message and the app was crashing. I had thought the PINRemoteImageManagerResult block was on the main thread, however it turns out that it wasn't - therefore ensuring that the begin/end updates was called on the main thread fixed the issue.
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.tableView beginUpdates];
[self.tableView endUpdates];
});
Well, I just used the better part of a day trying to figure this out, so hopefully this alternative explanation saves somebody else some time.
I had a tableview which was giving this message sometimes, when loading. It turned out to be caused by KVO notifications for Core Data objects firing while the view was loading. (On observing a change, my controller tried called reloadData on the tableview in question. Fixed by not observing the objects until the view had finished loading (previously I started observing the object once it was assigned via the accessor)
TLDR: Check to see if you might be trying to reload your data from something other than the main thread.
Maybe this helps someone: i once had this error while refreshing a single table view cell. I meant to do something like
NSIndexPath *reloadRow = [NSIndexPath indexPathForRow:1 inSection:2];
[self._mainTableView reloadRowsAtIndexPaths:@[reloadWebViewRow]
withRowAnimation:UITableViewRowAnimationFade];
But accidentally, i typed
NSIndexPath *reloadRow = [NSIndexPath indexPathForItem:1 inSection:2];
Notice the difference of the two indexpaths: one is created with indexPathForItem
(wrong), the other with indexPathForRow
(correct).
This all resulted in very strange behaviour of the tableView and the error message in the headline.
It seems like my issue was triggered when I was trying to update the UI within a portion of the code that was a callback from a web call. I resolved by forcing UI updates to happen on the main thread. I used code like this.
void runOnMainQueueWithoutDeadlocking(void (^block)(void)){
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
I call it as follows inside of the success block of my background web call.
runOnMainQueueWithoutDeadlocking(^{
[self.tableView beginUpdates];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
});
Yet another condition...
This happened when, not wanting a header, I returned nil
.
Fix:
func tableView(tableView: UITableView,
titleForHeaderInSection section: Int) -> String? {
return ""
}
© 2022 - 2024 — McMap. All rights reserved.