Reputation: 4843
I have a UITableView
with 4 sections. Three of these sections have a header view.
The header view is a UITableViewCell
, which I am de-queueing as a normal cell in the viewForHeaderInSection:
delegate.
If I insert or delete a row from any section, the other tableview
header cells disappear.
I'm assuming this has something to do with cell reuse, however the cells initially all appear on screen (all three headers appear onscreen at the same time).
I've tried reloading the other sections after the insert or delete, but that doesn't help.
Here's some code:
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
switch (section) {
case kSectionCardInformation:
case kSectionContactInformation:
case kSectionTags: {
static NSString *CellIdentifier = @"EditContactHeaderCell";
EditContactHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell;
}
default:
return nil;
}
}
And here is where I delete the row in the revelant section:
- (void)deleteTag:(CDTag *)tag {
[self.tableView beginUpdates];
NSMutableArray *objects = [self.sections objectAtIndex:kSectionTags];
if ([objects containsObject:tag]) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[objects indexOfObject:tag] inSection:kSectionTags];
[objects removeObject:tag];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationMiddle];
[self.contact deleteTag:tag];
}
[self.tableView endUpdates];
}
Any help, greatly appreciated.
Upvotes: 32
Views: 9468
Reputation: 386
Do not return your FooterCell or HeaderCell , or your reusable identifier. Return the reuseIdentifier.contentView. For me it's:
return headerCell!.contentView.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableHeaderFooterView(withIdentifier:"CustomViewHeaderView") as! CustomViewHeaderView
return headerCell.contentView
}
Upvotes: 2
Reputation: 1384
For Swift 4,5
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let containerView = UIView()
guard let headerCell = tableView.dequeueReusableCell(withIdentifier: "MyHeaderView") as? MyHeaderView else { fatalError(" Failed to load MyHeaderView") }
containerView.addSubview(headerCell)
return containerView
}
Upvotes: 6
Reputation: 513
Returning the contentView
of the cell
worked nicely for me. No need to wrap the cell in a UIView
.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
return cell.contentView
}
Upvotes: 20
Reputation: 141
Correct way to resolve this problem is to use UITableViewHeaderFooterView instead of using UITableViewCell for header section. Like @Francois Nadeau answered.
For more detail on how to use UITableViewHeaderFooterView for header section please see this answer: https://stackoverflow.com/a/36931047
Upvotes: 2
Reputation: 7463
Adding comment since I had the same problem... The problem was that I too was using a UITableViewCell as a header instead of using an UITableViewHeaderFooterView.
To fix the problem:
Register this nib inside your viewDidLoad function
override func viewDidLoad() {
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.register(UINib(nibName: "NibFileName", bundle: nil), forHeaderFooterViewReuseIdentifier: "CustomViewHeaderView")
}
Dequeue your reusable HeaderFooterView from the viewForHeaderInSection function:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableHeaderFooterView(withIdentifier:"CustomViewHeaderView") as! CustomViewHeaderView
return cell
}
This fixed my disappearing Header. I hope it can help others.
Upvotes: 18
Reputation: 25692
I dont know why are you are using tableview cell for header, but my assumption is that
You have missed the break statement
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
switch (section) {
case kSectionCardInformation:
break;
case kSectionContactInformation:
break;
case kSectionTags: {
static NSString *CellIdentifier = @"EditContactHeaderCell";
EditContactHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell;
}
default:
return nil;
}
}
Check nil
condition before returning the cell, if it was nil then create the cell.
static NSString *CellIdentifier = @"EditContactHeaderCell";
EditContactHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
return cell ?: createdCellNewly;
Updates:
Then check your numberOfSectionsInTableView:(UITableView *)tableView
method returns the proper count.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// returning count is correct?
}
Check and set the tableview's delegate & datasource.
Upvotes: -1
Reputation: 748
Just wrap your UITableViewCell into a UIView.
- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
switch (section) {
case kSectionCardInformation:
case kSectionContactInformation:
case kSectionTags: {
static NSString *CellIdentifier = @"EditContactHeaderCell";
EditContactHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIView * view = [[[UIView alloc] init] autorelease];
[view addSubview:cell];
//setup the view's frame: fixed, autolayout, ...
return view;
}
default:
return nil;
}
}
Upvotes: 25