What is the meaning of the no index path for table cell being reused message in iOS 6/7?
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.
No index path for table cell being reused
I worked this out after a few days. In my custom cell I had a textView, when I was adding it to the contentView I was doing this:
[self.cellTextView setClearsOnInsertion:YES];
This was the cause of the issue; incase anyone else has a similar problem.
Happy coding :-)
no index path for table cell being reused leading to app crash
You can try to disable touches on the webView and intercept the touches in the didSelectRow.
Also instead of [tableView reloadData]
try using:
[tableView beginUpdates];
[tableView endUpdates];
It almost always works better for collapsing tableviews.
Custom table cells iOS 6
See the documentation of dequeueReusableCellWithIdentifier:
for iOS 6:
If you registered a class for the specified identifier and a new cell
must be created, this method initializes the cell by calling its
initWithStyle:reuseIdentifier: method.
You have registered a class with
[SettingsTable registerClass:[TextFieldTableCell class] forCellReuseIdentifier:@"textFieldCell"];
and therefore dequeueReusableCellWithIdentifier:
never returns nil
.
You should create the subviews of the table view cell in the initWithStyle:reuseIdentifier:
method of your TextFieldTableCell
class, for example:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 0, 295, 43)];
self.textField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
[self.contentView addSubview:self.textField];
}
return self;
}
An alternative is to implement prepareForReuse
in your TextFieldTableCell
class to "clean up" the cell content for reuse.
Is changing the table height by changing its contrains good practice?
Things I look out for to avoid the problems you are in,
- Try avoiding any constants or values for dimensions as much as possible.
- Use
constraints
and try defining it in exactly one place ( StoryBoard, Xib, or in code).
As its height to be determined by its content attaching to screen edge won't work.
As for your queries,
- Try checking if any conflicting constraints appear on the storyboard and code. Like if the whole
tableview
is defined in the storyboard, why nottableView.rowHeight = 50
remains there as well. - While deleting,
tableView.deleteRows()
have.autometic
animation. As per doc,case automatic = 100 // available in iOS 5.0. chooses an appropriate animation style for you
. Let's set that to.none
.
Kindly check if the reviewed snippet below works.
var data = [1,2,3,4,5,6,7,8,9,10]
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var tableViewHeight: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 50
tableViewHeight.constant = CGFloat(data.count) * tableView.rowHeight
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
self.tableViewHeight.constant = CGFloat(self.data.count) * self.tableView.rowHeight
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "\(data[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
// I think this is causing the problem.
if editingStyle == .delete {
data.remove(at: indexPath.row)
// use no animation
tableView.deleteRows(at: [indexPath], with: .none)
// wont update the constraint here.
// self.tableViewHeight.constant = CGFloat(self.data.count) * self.tableView.rowHeight
}
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(!isEditing, animated: true)
tableView.setEditing(!tableView.isEditing, animated: true)
}
}
Also check these as well if haven't already,
- Dynamic UITableView height
- Change UITableView height dynamically
Use a UITableViewCell as tableHeaderView
Not sure how you're setting up your custom cell, but if it has a nib associated with it, you can do this:
HeaderUserLoggedOutCell *userLoggedOutCell = [[[NSBundle mainBundle] loadNibNamed:@"HeaderUserLoggedOutCell" owner:self options:nil] objectAtIndex:0];
// customize your cell in whatever way you need to
self.menuTableView.tableHeaderView = userLoggedOutCell.contentView;
No need to add your custom cell to a separate UIView.
Related Topics
Crashlytics: "We'Re Missing a Dsym to Process Crashes"
Dyld'_Abort_With_Payload: Without an Error Message
Connect Objective-C Framework to Swift iOS 8 App (Parse Framework)
How to Display .Svg Image Using Swift
How to Crop Uiimage on Oval Shape or Circle Shape
Change the Uitableviewcell Height According to Amount of Text
How to Reset the iOS Simulator from the Command Line
Tablefooterview Property Doesn't Fix the Footer at the Bottom of the Table View
Xcode Nsmanagedobject Subclass Contains Optionals When They Are Marked as Non-Optional
Alternative to Dtsendsignalflag to Identify Key Events in Instruments
Presenting a Uialertcontroller Properly on an iPad Using iOS 8
Uilabel Layer Cornerradius Negatively Impacting Performance
Xcode Is Looking for Core Data Entity Names with Dot; Not Compiling
How to Change Device Volume on iOS - Not Music Volume
Wkwebview Does Load Resources from Local Document Folder