42

When you create a UITableView with the UITableViewStyleGrouped style, it adds quite a lot of space in between the actual tableviewcells and the borders of the table's frame. This space is above, below, to the left, and to the right of the tableviewcells.

You can change the space between tableviewcells themselves by:

[myTableView setSectionHeaderHeight:0];
[myTableView setSectionFooterHeight:25];

However, even by doing that, there's still this annoying space between the top of the frame and the first tableviewcell. Furthermore, there's a ton of space still in between the left of the frame and the tableviewcell, as well as the right side of the frame and the tableviewcell.

-=-=-=-=-=-=-

Is there a way to manipulate that space (resize it)? My only solution thus far is to make the size of the frame larger than the screen to fake out the program into having that "blank space" outside of the screen, thus removing it. However, this is obviously not optimal and a clear hack.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
Highrule
  • 1,915
  • 3
  • 19
  • 23
  • In order to achieve such a custom behaviour I would suggest the right way of doing it: `UICollectionView` – art-divin Jan 02 '14 at 22:13
  • If you're using iOS 15 or greater, you have to consider `sectionHeaderTopPadding`: https://stackoverflow.com/a/69322250/2611730 – monstermac77 May 26 '23 at 03:25

12 Answers12

135

The space is there because of the UITableView's tableHeaderView property. When the the tableHeaderView property is nil Apple defaults a view. So the way around this is to create an empty view with a height greater than 0. Setting this overrides the default view thereby removing the unwanted space.

This can be done in a Storyboard by dragging a view to the top of a tableView and then setting the height of the view to a value of 1 or greater.

Or it can be done programmatically with the following code:

Objective-C:

CGRect frame = CGRectZero;
frame.size.height = CGFLOAT_MIN;
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:frame]];

Swift:

var frame = CGRect.zero
frame.size.height = .leastNormalMagnitude
tableView.tableHeaderView = UIView(frame: frame)

Comments

As others have noted you can use this same solution for footers.


Sources and Acknowledgements

See the Documentation for more details on the tableHeaderView property.

Thanks to @liushuaikobe for verifying using the least positive normal number works.

starball
  • 20,030
  • 7
  • 43
  • 238
James Nelson
  • 1,793
  • 1
  • 20
  • 25
  • 6
    after reading ~10 other answers around scroll view insets and default contentEdgeInsets etc, this seems the best solution for Grouped style embedded in UIViewController. – gravitron May 22 '16 at 12:52
  • 3
    One line solution `self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)]` – liushuaikobe Feb 19 '17 at 15:14
  • 1
    @liushuaikobe: Does `CGFLOAT_MIN` work? I seem to remember trying this without success when I wrote the answer. – James Nelson Feb 20 '17 at 19:32
  • 2
    If you call heightForHeaderInSection don't return zero otherwise the code above will not working – Mohammed Saleh Nov 21 '20 at 16:20
  • This is half correct (at least for me). The reason for the extra space is correct but the solution didn't work for me, so I had to create and register separate header & footer classes and then give them a height of zero to remove the extra space from the grouped uitableview. – AfnanAhmad Aug 11 '21 at 10:58
  • Thanks for this, I already had a section header and was wondering why is there still some kind of header. Turns out it was the table's header, not the section's header. Interestingly for some reason it does not seem to appear if there are many rows to cover the whole screen; it seems to magically remove the table's header in this case. – CyberMew Nov 12 '21 at 08:50
  • Also take note as per https://stackoverflow.com/questions/42246153/returning-cgfloat-leastnormalmagnitude-for-uitableview-section-header-causes-cra it performs differently for iOS 10 and below. – CyberMew Nov 12 '21 at 08:53
18

Answer in Swift 4

If the table view is selected in interface builder and in the attributes inspector the style "Grouped" is selected, enter the following code in your view controller to fix the extra header space issue.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNonzeroMagnitude
}
F. Morales
  • 437
  • 6
  • 5
12

Use it in the viewDidLoad() method.

tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: Double.leastNormalMagnitude))
Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
  • 1
    You can simply use: `tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: .leastNormalMagnitude))`. No need to explicitly cast to a Double. – David Topolansky Aug 20 '19 at 01:18
10

Single line solution:

Objective-C

self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];

Swift

self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: Double(FLT_MIN)))
Leszek Szary
  • 9,763
  • 4
  • 55
  • 62
8

Follow these steps to save your day.

Select grouped attributes from the storyboard.

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 
     return CGFloat.leastNonzeroMagnitude 
}

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 
     return CGFloat.leastNonzeroMagnitude 
}

If you are using ios 15 do this also —

if #available(iOS 15.0, *){ 
    self.tableViewSavedRecent.sectionHeaderTopPadding = 0.0 
}
CodeChanger
  • 7,953
  • 5
  • 49
  • 80
Ankit Soni
  • 129
  • 1
  • 2
6

For iOS 11.0+

tableView.contentInsetAdjustmentBehavior = .never
Lane Faison
  • 278
  • 4
  • 7
5

If the style of your tableView is UITableViewStyleGrouped, then you have to pay attention to the delegate of the height of SectionHeader or SectionFooter, cause this needs to be implemented right under this case.

The return value should not be 0, even if the SectionHeader or the height of SectionFooter is 0, it needs to be a very small value; try CGFLOAT_MIN.

For my example:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
if (section == [self.dataArray indexOfObject:self.bannerList]) {
    return 46;
}
return CGFLOAT_MIN;

}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return CGFLOAT_MIN;
} 

Make sure you implemented these two methods, and the value is right, and the top margin will be fixed.

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
MichaelMao
  • 528
  • 6
  • 15
4

You need to set footer too

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
  return 0;
}

-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
  return [[UIView alloc] initWithFrame:CGRectZero];   
}
user5226582
  • 1,946
  • 1
  • 22
  • 37
4
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNonzeroMagnitude
}

Below location icon is table with top spacing zero.

HK boy
  • 1,398
  • 11
  • 17
  • 25
Mohd Danish Khan
  • 1,044
  • 11
  • 12
3

I had to combine both delegate functions for it to work:

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return .leastNonzeroMagnitude
}

func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    return UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: .leastNonzeroMagnitude))
}
Xavier Chia
  • 203
  • 3
  • 5
1

None of above solution worked for me

In my case these setting was set to manual i just changed to Automatic

enter image description here

Anil Kumar
  • 1,830
  • 15
  • 24
1

If you are using a TableHeaderView with an insetGroup styled UITableView you can do the following:

class CustomTableHeaderView: UIView {
    
    init() {
        super.init(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
        --- do your header view setup here. ---
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
dan
  • 873
  • 8
  • 11