731

Starting in iOS7, there is additional space at the top of my UITableView's which have a style UITableViewStyleGrouped.

Here is an example:

enter image description here

The tableview starts at the first arrow, there are 35 pixels of unexplained padding, then the green header is a UIView returned by viewForHeaderInSection (where the section is 0).

Can anyone explain where this 35-pixel amount is coming from and how I can get rid of it without switching to UITableViewStylePlain?


Update (Answer):

In iOS 11 and later:

tableView.contentInsetAdjustmentBehavior = .never
11
  • are you using the latest iOS 7? Some of these TYPES of inconsistencies (but not all, and perhaps not this one) have been cured during in the later dev previews. I should know: I procrastinated so much some of the problems disappeared. Sep 18, 2013 at 20:14
  • Check answer here - stackoverflow.com/a/18986158/1463604
    – Nishant
    May 27, 2015 at 12:37
  • 40
    self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, CGFLOAT_MIN)]; note: 0.0f is just ignored if you use it in the height of the rect. So we use the nearest-to-zero CGFloat possible (at least this "worked" for me... just not ideal solution). Oct 14, 2015 at 13:59
  • 2
    @AlejandroIván your comment just made my night. I've got a tableView with grouped prototypes. I'm using numberSections = data.count and setting numberRows = 1. I set a heightForFooterInSection to make a clean space between each and for some reason a blank tableHeaderView appeared. Oct 21, 2015 at 5:33
  • 2
    if #available(iOS 15.0, *) { table.sectionHeaderTopPadding = 0 } Put this code it will work
    – Vinayak
    Sep 29, 2022 at 6:44

78 Answers 78

868

I was helped by the following:

YouStoryboard.storyboard > YouViewController > Attributes inspector > Uncheck - Adjust scroll view insets.

enter image description here

23
  • 42
    I think this is the correct way of removing that padding, instead of tampering with edgeInset values.
    – Hgeg
    Nov 24, 2013 at 17:18
  • 24
    This didn't work for me -- I have an opaque navBar above and this turned off pushes the content under it.
    – slycrel
    Jan 7, 2014 at 18:08
  • 5
    Does not work when using custom collectionview. (When tableview is inside collectionviewcell) Jul 27, 2014 at 12:16
  • 6
    Didn't work for me; Only thing that worked was switching to Plain instead of Grouped
    – shim
    Mar 8, 2015 at 20:56
  • 29
    I had this problem with a TableViewController inside a container view. I had to set this property not directly on the TableViewController which was embedded, but on the view controller which contained the container view. Then it worked. Nov 14, 2015 at 12:22
346

I played around with it a bit more and it seems like this is a side-effect of setting the tableView's tableHeaderView = nil.

Because my tableView has a dynamically appearing tableHeaderView, when I need to hide the tableHeaderView, instead of doing self.tableView.tableHeaderView = nil;, I do:

self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)];

I like this solution better than setting a somewhat arbitrary contentInset.top because I use the contentInset.top dynamically as well. Having to remember to remove an extra 35px whenever I recalculate contentInset.top is tedious.

13
  • 4
    Great solution! Indeed, you have to set it to 0.01f to get rid of the default table view header view as in your code. Sep 27, 2013 at 23:16
  • 2
    BTW, this is also possible to do with one drag & drop in the Interface Builder. Anyway, thanks! :) Nov 7, 2013 at 16:31
  • 9
    you sir deserves a medal for this Nov 18, 2013 at 8:30
  • 8
    Bear in mind that a 0.01f height view at the top of your table view will mean all the cells beaneath are misaligned (first cell with have a Y origin of 0.01, the next of cell_height+0.01, etc) so the contents of those cells will be misaligned. (Turn on Debug > Color Misaligned Images in the simulator to see this for yourself.) You don't want to do that. Apr 25, 2014 at 11:19
  • 4
    It's better to use UITableViewHeaderFooterView instead of UIView. And CGFLOAT_MIN works the same as 0.01f but better in theory.
    – Jaybo
    Feb 14, 2015 at 6:47
195

Try changing the contentInset property that UITableView inherits from UIScrollView.

self.tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);

It's a workaround, but it works

3
  • 7
    contentTableView.contentInset = UIEdgeInsetsMake(-20, 0, -20, 0); worked best for me because there were 20 extra pixels at the top and bottom.
    – Brian
    Jan 16, 2014 at 19:31
  • 1
    Although this "brute force" solution works, I think the bottom ones (specifically the automatically adjust insets) should be ranked higher.
    – eladleb
    Apr 2, 2014 at 13:37
  • 4
    total hack but iOS is garbage so what can you do.
    – AlexK
    Jul 1, 2020 at 16:50
180

For IOS 7 if you are allocing a tableview in a view controller you may look into

self.edgesForExtendedLayout = UIRectEdgeNone;

your problem seemed similar to mine

Update:

Swift in iOS 9.x:

self.edgesForExtendedLayout = UIRectEdge.None

Swift 3 :

self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0)
4
  • 3
    Worked on my plain UITableView. The issues stems from the fact my UITableView was on a UIViewController inside a UINavigationController which caused the table content to drop down 44 points so initial content wasn't up behind the navBar. That wasn't needed with my layout though, so it just caused issues. Eventually I changed my code to automaticallyAdjustsScrollViewInsets which worked also.
    – DBD
    Jun 23, 2014 at 14:32
  • This property is applied only to view controllers that are embedded in a container such as UINavigationController. The window’s root view controller does not react to this property. The default value of this property is all. ..I feel like the default should be 0? Where does this have an advantage.
    – Desh__
    Jun 13, 2017 at 21:12
  • 5
    More elegant with Swift 3: edgesForExtendedLayout = [] Aug 9, 2017 at 22:58
  • Hello @yeahdixon What software do you use to make the pink arrow ? thanks in advance
    – iArezki
    Oct 4, 2017 at 9:30
140
self.automaticallyAdjustsScrollViewInsets = NO;

try, you can deal with it!

7
  • This works great to hide the tableHeaderView in iOS 7.0, but it isn't supported in older versions.
    – Brian
    Jan 16, 2014 at 19:42
  • Works great under iOS 7. Jul 24, 2014 at 22:45
  • 4
    Important: Make sure you do this in the container view controller, if your UITableView is placed on a controller which is then embedded into another controller, do this in the embedding top controller, not directly the one where you put the UITableView (where AutoLayout will take care of things). Aug 14, 2014 at 10:29
  • This is better than uncheck Adjust scroll view insets. Because sometimes we don't use storyboard to build our UI.
    – JW.ZG
    Sep 19, 2016 at 20:02
  • 3
    This was deprecated in iOS 11.0. Xcode will warn you about this. Use this instead, on the scroll view that you don't want insets automatically adjusted on: self.tableView.contentInsetAdjustmentBehavior = .never Aug 20, 2019 at 1:09
100

Solution for iOS 15:

if #available(iOS 15.0, *) {
  tableView.sectionHeaderTopPadding = 0
}

To fix in a whole project:

if #available(iOS 15.0, *) {
    UITableView.appearance().sectionHeaderTopPadding = 0
}

More details: Extra padding above table view headers in iOS 15

Note: This only applies to UITableView.Style.plain.

7
  • 2
    Perfect, thanks! None of the other answers here addressed the issue for me.
    – Joel
    Oct 7, 2021 at 9:09
  • 2
    Thanks!! it is working perfectly.
    – G Ganesh
    Nov 12, 2021 at 12:54
  • 2
    This. Thank you. I beat my head against a wall for a while trying to figure this out. I upgraded my phone to iOS 15, and any new builds of my app manifested this behavior. However, my existing build on the app store did not. Thanks again.
    – Dan
    Nov 13, 2021 at 19:00
  • Reference to member 'sectionHeaderTopPadding' cannot be resolved without a contextual type
    – Ahmadreza
    Dec 29, 2021 at 10:01
  • 3
    This is pure gold! Jan 17, 2023 at 22:55
81

You could detect if your app is running iOS7 or greater and add this two methods in your table view delegate (usually in your UIViewController code)

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

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

This maybe is not an elegant solution but works for me

Swift version:

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

override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}
6
  • 1
    This worked for me. UITableView adds space on top for lots of different reasons. Specifically, related to OP, the problem only happens for grouped style table view. And this solution fixed the problem.
    – RajV
    Oct 28, 2013 at 18:18
  • 5
    You can use CGFLOAT_MIN instead of 0.001 it gives you the smallest absolute value of CGFloat.
    – KaroCodes
    Sep 11, 2015 at 9:07
  • 2
    This is the correct answer since the real feature is that padding is there only in the grouped style table view and is ignored if you specify the header/footer May 6, 2016 at 10:55
  • This should be marked as the correct answer. A delegate method to override and it answers the question. At least try this first if you read this far down all the hacks. Try tweeting : -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { //return CGFLOAT_MIN; return 30.0f; } Aug 2, 2018 at 2:25
  • Nice! As a bonus, if you want a little header on top and more in between the grouped sections, you can use the following: override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return section == 0 ? 14 : 24 } Apr 16, 2019 at 9:04
60

I have found the cause of my original bug and created a sample project showcasing it. I believe there is an iOS7 bug.

As of iOS7, if you create a UITableView with the Grouped style, but do not have a delegate set on first layout, then you set a delegate and call reloadData, there will be a 35px space at the top that will never go away.

See this project I made showcasing the bug: https://github.com/esilverberg/TableViewDelayedDelegateBug

Specifically this file: https://github.com/esilverberg/TableViewDelayedDelegateBug/blob/master/TableViewDelayedDelegateBug/ViewController.m

If line 24 is active,

[self performSelector:@selector(updateDelegate) withObject:nil afterDelay:0.0];

there will be an extra 35 px space at the top. If line 27 is active and 24 is commented out,

self.tableView.delegate = self;

no space at the top. It's like the tableView is caching a result somewhere and not redrawing itself after the delegate is set and reloadData is called.

7
  • 21
    I'd add that even if there is a delegate but the delegate's tableView:heightForHeaderInSection: and tableView:heightForFooterInSection: returns 0 you will also have this problem. Implementing the protocol methods above AND returning 0.01f fixed it for me. Oct 7, 2013 at 5:25
  • 1
    YES!! I've tried 3 so called solutions, and this was the one! Brilliant, thanks :D Oct 8, 2013 at 8:43
  • perfect. Anyone reported a bug because I think this is not the intended behaviour.
    – Pushparaj
    Dec 2, 2014 at 5:49
  • great find! This is still happening in ios 9 (we're not using XIBs) but setting the delegate on init fixed the spacing (not in loadView or viewDIdLoad). Thank you! Oct 22, 2015 at 12:32
  • 2
    Setting estimatedHeight for header helped me
    – Viktor
    Sep 7, 2018 at 16:09
50

Uncheck "Adjust Scroll View insets"

enter image description here

2
  • I needed this option for another View Controller of mine, and apparently when I made a new VC, the change carried over. Thanks for this!
    – David
    Mar 31, 2017 at 4:16
  • Yeah! Works, justo set it in ContainerView and works! Oct 2, 2018 at 16:56
46

Another quick comment... even in XCode 6.1, there is a bug with vertical spaces appearing at the top of UIScrollViews, UITextViews and UITableViews.

enter image description here

Sometimes, the only way to fix this issue is to go into the Storyboard and drag the problem control so it's no longer the first subview on the page.

enter image description here

(My thanks to Oded for pointing me in this direction... I'm posting this comment, just to add a few screenshots, to demonstrate the symptoms and fix.)

17
  • 1
    Note that this bug, errrr, issue also happens in iOS 8 if you have a UITextView as the first sub-control on your page... so it's not just a UITableView issue. Jan 29, 2015 at 9:13
  • 1
    Out of all solution only this hack worked for me. A weird fix to a weird bug. I've faced this issue with UITableview.
    – Mesbah
    Jun 16, 2015 at 8:25
  • 4
    1 million thank you's! This is the only solution which worked for me.
    – user139816
    Aug 12, 2015 at 11:58
  • 1
    (I'm amazed its 18 months later, and readers are still voting up this answer. Has Apple seriously not fixed this issue yet ?!) Oct 14, 2016 at 9:44
  • 1
    saved my life! thanks. do you know how long it took to find this simple little "fix"? grrh.
    – Mc.Stever
    Nov 25, 2016 at 13:34
43

While using grouped TableView use this to avoid border cutting in viewWillAppear

self.tableView.contentInset = UIEdgeInsetsMake(-35, 0, 0, 0);
1
  • Tried all the others. This is the one that worked! Thx
    – Michael
    Jun 4, 2020 at 19:28
40

According to this transition guide for iOS7 by Apple, the scroll view’s content insets is automatically adjusted. The default value of automaticallyAdjustsScrollViewInsets is set to YES.

The UIViewController which has the UITableView should set this property to NO.

self.automaticallyAdjustsScrollViewInsets = NO;

This will do the trick.

EDIT 1:

Also, one could try -

self.navigationController.navigationBar.translucent = YES;

This also removes the extra padding on the top.

3
  • Very good answer, unless it don't exactly answer the question. Esilver talks about 35px gap, but iOS7 adds extra 20px header: equal to the status bar height.
    – Martin
    Feb 28, 2014 at 10:37
  • This is the answer to a different problem.
    – entonio
    Nov 9, 2014 at 4:09
  • Thank you it worked for me, in my particular case I had a tableviewcontroller embedded in the viewcontroller, and by setting automaticallyAdjustsScrollViewInsets = false in the viewcontroller the top gap disappeared
    – Alexey
    Mar 2, 2016 at 9:37
39

A lot of the previous answers above are too hacky. They would break at anytime in the future if Apple decides to fix this unexpected behavior.

Root of the issue:

  1. a UITableView doesn't like to have a header with a height of 0.0. If what's you're trying to do is to have a header with a height of 0, you can jump to the solution.

  2. even if later you assign a non 0.0 height to your header, a UITableView doesn't like to be assigned a header with a height of 0.0 at first.

Solution:

Then, the most simple and reliable fix is to ensure that your header height is not 0 when you assign it to your table view.

Something like this would work:

// Replace UIView with whatever class you're using as your header below:
UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.tableView.bounds.size.width, CGFLOAT_MIN)];
self.tableView.tableHeaderView = tableViewHeaderView;

Something like this would lead to the issue at some point (typically, after a scroll):

// Replace UIView with whatever class you're using as your header below:
UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = tableViewHeaderView;
2
  • Finally, I found the answer that works. Thanks. Besides, I learnt that tableView.tableHeaderView is actually an accessory view above row content. I was confused with section headers all the way until your answer came out.
    – Joe Huang
    May 31, 2016 at 1:40
  • 1
    CGFLOAT_MIN has been replaced with CGFloat.leastNormalMagnitude in Swift 3
    – Clay Ellis
    Apr 3, 2017 at 18:12
29

Storyboard:

Just uncheck: Adjust Scroll View Insets in View Controller's options

enter image description here

Code:

self.automaticallyAdjustsScrollViewInsets = false
2
  • 2
    using xcode 7 I don't see Attribute inspector > Layout, where should I add self.automaticallyAdjustsScrollViewInsets = false
    – alex
    Jan 18, 2016 at 10:40
  • in view did load.
    – CW0007007
    Jul 11, 2018 at 5:35
28

This code worked for me, The best answer for me that was written in objective-C at up-side so I converted it into Swift.

For Swift 4.0+

self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: .leastNonzeroMagnitude))

Just write this into viewDidLoad() and it will work like a charm.

For iOS 15+, above one won't work, so use this:-

 if #available(iOS 15.0, *) {
      tableView.sectionHeaderTopPadding = 0
 }

For iOS 15+, if you want to apply change for your whole project, so use this:-

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    if #available(iOS 15.0, *) {
        UITableView.appearance().sectionHeaderTopPadding = 0.0
    }
}
2
  • to avoid values, I'd recommend to put ".leastNonzeroMagnitude" instead of 0.01; Aug 23, 2021 at 10:15
  • 1
    giving width is the key, i was using this code but giving zero to width
    – Ryan110
    Apr 16, 2023 at 21:12
25

This is the solution for iOS 10 using Swift 3:

You can get rid of top and bottom paddings by implementing the following methods from the UITableViewDelegate.

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

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
{
   return CGFloat.leastNormalMagnitude
}
2
  • Second page on SO helped me.... I dont know why, maybe because of the AutomaticDimension, maybe because of the Constraints with the VFL, anyhow, thank you! ozi bua ist brav! :D
    – Pentarex
    Jan 21, 2017 at 1:41
  • These are the section headers and footers. The question relates to the whole table header. Also, there is nothing specific to Swift3 or iOS 10 in either delegate method (they've been around since forever). Apr 20, 2017 at 6:23
16

So I was trying every method here, and this time none of them helped. My case was a grouped table view on iOS 9. I don't really know why and how I found out this one, but for me, setting the tableViewHeader with a UIView with at least 0.01 height worked out. CGRectZero didn't help, nothing really helped:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 0.01))
2
  • 1
    Thank. It help me!
    – Ten
    Dec 25, 2020 at 10:31
  • Saved my day, mate.
    – jacob
    Apr 22, 2021 at 11:59
15

Simply add the following to your viewDidLoad in your VC:

self.automaticallyAdjustsScrollViewInsets = NO;
1
  • This fix worked and I prefer it to manually setting the insets using magic numbers. Thanks!
    – imobilizer
    May 23, 2016 at 14:41
14

In my case this was what helped me. I'm supporting ios6 also.

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    self.edgesForExtendedLayout = UIRectEdgeNone;
    self.extendedLayoutIncludesOpaqueBars = NO;
    self.automaticallyAdjustsScrollViewInsets = NO;
}
7
  • Not sure what this does but it worked perfectly. Could you give some explanation?
    – Matt Wolfe
    Sep 26, 2013 at 18:22
  • @MattWolfe I was lost, and found this solution, not sure either why this is happening. My guess is that controller is deciding that tableview needs an inset, because of the status bar(or in other cases toolbar/tabbar) so it automatically adds it. I'm really struggling with some of the new iOS7 "features". Maybe some one understands it, and has a real explanation on this?
    – Lukas
    Sep 27, 2013 at 7:54
  • Spent the last 2 days porting a relatively small app to iOS 7 and still having minor issues.. I fix it in ios 7 it breaks in 6 and vice versa.. Driving me nuts!
    – Matt Wolfe
    Sep 27, 2013 at 8:08
  • This is a different problem than OP. Even with this, for grouped table view, an extra space is added on the top.
    – RajV
    Oct 28, 2013 at 18:15
  • 1
    this seems to be the key line: self.automaticallyAdjustsScrollViewInsets = NO; just setting that removed the extra space I had.
    – Mike M
    Oct 31, 2013 at 13:12
13

This is how it can be fixed easily in iOS 11 and Xcode 9.1 through Storyboard:

Select Table View > Size Inspector > Content Insets: Never

3
  • 1
    Worked for me :)
    – bhupinder
    Mar 7, 2018 at 10:46
  • Great! Thanks :)
    – Saeed Ir
    Mar 8, 2018 at 3:15
  • 1
    This is instead of automaticallyAdjustsScrollViewInsets in ios 11
    – Nike Kov
    Oct 5, 2018 at 10:46
12

2022 answer:

You just do this

tableView.contentInsetAdjustmentBehavior = .never

which is undocumented

Bizarre subtle gotchya ->

Tableviews have a very strange behavior these days:

  1. On devices with a notch (XR, etc) it will without telling you add more inset BUT ONLY IF the table starts at the physical top of the screen.

  2. If you start NOT at the top of the screen, it won't do that, but

  3. Both of those cases are >> unrelated << to safeAreaInsets ....... which is very confusing

All of that is totally undocumented ... you can waste hours figuring this out.

If you do need your measurements to start actually from the top of the screen/table,

in fact simply go:

tableView.contentInsetAdjustmentBehavior = .never

A good example is obviously when you add some sort of banner or similar thing over the top of a table, which is common these days, and you just set the top inset of the table to whatever height your banner/etc becomes when it's running.

To do that, you must use the

tableView.contentInsetAdjustmentBehavior = .never

call :/

Bonus gotchya

Don't forget that almost always these days, you're loading some information (user pictures, description, whatever) dynamically, so you can't set such values to the final needed value until the info arrives. Another gotchya. :/

So you'd have code like:

func setTableOffsetOnceFlagAreaSizeIsKnown() {
    tableView.contentInset.top = yourSpecialFlagViewUpTop.bounds.height
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    setTableOffsetOnceFlagAreaSizeIsKnown()
}
11

Swift: iOS I had tableview on scroll view .. when I was click "Back" on the same screen. Scroll view take more space on top.. to solve this I have used :

 self.automaticallyAdjustsScrollViewInsets = false

A Boolean value that indicates whether the view controller should automatically adjust its scroll view insets. Default value is true, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to false if you want to manage scroll view inset adjustments yourself, such as when there is more than one scroll view in the view hierarchy.

11

To be specific, to remove tableviewHeader space from top i made these changes:

YouStoryboard.storyboard > YouViewController > Select TableView > Size inspector > Content insets - Set it to never.

enter image description here

4
  • What's the additional information other than the screenshot in comparison to this answer?
    – Artjom B.
    Apr 14, 2018 at 12:34
  • it is the same I guess, I didn't find that answer when I was looking for a solution. Should I delete my answer then..?
    – user832
    Apr 17, 2018 at 6:53
  • Not if you can expand a bit on your answer by describing why Content insets = Never actually solves this issue (how does this option work?).
    – Artjom B.
    Apr 17, 2018 at 19:23
  • When content insets is set to never, the tableView will not scroll up on textField editing. Apr 30, 2019 at 9:26
10

Thanks to the answer by @Aurelien Porte. Here is my solution

Cause of this issue:-

  1. a UITableView doesn't like to have a header with a height of 0.0. If what's you're trying to do is to have a header with a height of 0, you can jump to the solution.
  2. even if later you assign a non 0.0 height to your header, a UITableView doesn't like to be assigned a header with a height of 0.0 at first.

In ViewDidLoad:-

self.edgesForExtendedLayout = UIRectEdge.None

self.automaticallyAdjustsScrollViewInsets = false

No Need For Something Like This :-

self.myTableview.contentInset = UIEdgeInsetsMake(-56, 0, 0, 0)

In heightForHeaderInSection delegate:-

if section == 0
    {
        return 1
    }
    else
    {
        return 40; // your other headers height value
    }

In viewForHeaderInSection delegate :-

if section == 0 
{  
   // Note CGFloat.min for swift
   // For Objective-c CGFLOAT_MIN 
   let headerView = UIView.init(frame: CGRectMake(0.0, 0.0, self.myShaadiTableview.bounds.size.width, CGFloat.min)) 
   return headerView
}
else
{ 
   // Construct your other headers here 
}
10

The only thing that worked for me was:

Swift:

tableView.sectionHeaderHeight = 0
tableView.sectionFooterHeight = 0

Objective-C:

self.tableView.sectionHeaderHeight = 0;
self.tableView.sectionFooterHeight = 0;

Also, I still had an extra space for the first section. That was because I was using the tableHeaderView property incorrectly. Fixed that as well by adding:

self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 0.01))
2
  • Works for me for Swift 4.2. Thanks
    – Sylar
    Feb 14, 2019 at 9:38
  • Tried everything in this page, for iOS13 grouped tableview with header view. self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 0.01)) . fixed the issue.
    – Ning
    Sep 12, 2019 at 22:43
9

I'm assuming that is just part of the new UITableViewStyleGrouped styling. It is in all grouped table views and there doesn't seem to be any direct way to control that space.

If that space is being represented by a UIView, it would be possible to search through all the subviews of the UITableView to find that specific view and edit it directly. However, there is also the possibility that that space is just a hardcoded offset before headers and cells start and there won't be any way to edit it.

To search through all subviews (I would run this code when the table has no cells, to make it a little easier to read the output):

- (void)listSubviewsOfView:(UIView *)view {

    // Get the subviews of the view
    NSArray *subviews = [view subviews];

    // Return if there are no subviews
    if ([subviews count] == 0) return;

    for (UIView *subview in subviews) {

        NSLog(@"%@", subview);

        // List the subviews of subview
        [self listSubviewsOfView:subview];
    }
}
5
  • 3
    If UITableViews (to be more specific UITableViewCellScrollView) on iOS7 have taught us one thing, it's to leave the view hierarchy of built in classes alone. Sep 18, 2013 at 20:23
  • Good point. The other option is... to keep hacking for each iOS ;) Sep 18, 2013 at 20:28
  • Whoops, yeah. Meant to write that warning but forgot.
    – Kevin
    Sep 19, 2013 at 1:46
  • Kevin - I think you are right, this is by design. It appears that returning 0 for heightForHeaderInSection is the easiest way to remove this padding. For some reason on that particular instance it wasn't working for me, but it does work on other UITableViews.
    – esilver
    Sep 19, 2013 at 3:46
  • 1
    It's definitely "by design". If you paused execution and ran: po [((UIApplication *)UIApplication.sharedApplication).keyWindow recursiveDescription] you'll see that the table header, or first section header, or first cell (depending on what you use) naturally leaves a 35px border.... boo.
    – Mr. T
    Sep 21, 2013 at 6:54
9

My answer is going to be more general answer, but can be applied on this as well.

If the root view (of the ViewController) or the first child (subview) of the root view is subclass of the UIScrollView (or UIScrollView itself), and if

self.navigationController.navigationBar.translucent = YES;

framework will automatically set pre-calculated contentInset.


To avoid this you can do

self.automaticallyAdjustsScrollViewInsets = NO;

but in my case I wasn't able to do this, because I was implementing SDK which has UIView component which can be used by other developers. That UIView component contains UIWebView (which has UIScrollView as the first subview). If that component is added as the first child in the UIViewController's view hierarchy, automatic insets will be applied by system.

I've fixed this by adding dummy view with frame (0,0,0,0) before adding UIWebView.

In this case system didn't find subclass of the UIScrollView as the first subview and didn't apply insets

1
  • livesaver! thank you self.automaticallyAdjustsScrollViewInsets = false
    – ethanneff
    Jan 30, 2016 at 18:03
9

Swift 4 code: For tableview with no section headers you can add this code:

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

and you will get the header spacing to 0.

If you want a header of your specific height pass that value:

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

and the view from viewForHeaderinSection delegate.

2
  • This doesn't answer the question. The question was about where the extra spacing is coming from, not how to get rid of it. Feb 27, 2018 at 2:25
  • weird thing is that if u return 0 in heightForHeaderInsection u still get this extra space. It works perfect with CGFloat.leastNormalMagnitude ( least positive number)
    – ShadeToD
    Mar 17, 2019 at 9:20
9

This one line of code will make you happy.

override func viewDidLoad() {
        super.viewDidLoad()
        if #available(iOS 15.0, *) {
            tableView.sectionHeaderTopPadding = CGFloat(0)
        }
    }
1
  • Is it worked only .plain style tableView?
    – Abrcd18
    Feb 4 at 12:00
7

I had the same fix as arielyz. Once I moved the UITableView to be not the first subview of the parent view, it went away. My space was 20 px, not 35.

I wasn't able to recreate it in a portrait xib, only a landscape xib. I'll file a radar bug later if I can reproduce it in a simple demo app.

3
  • Ran into the same issue, wasn't able to solve it by changing the contentInset but this method worked, even though it's pretty hacky. For what it's worth, using the visual debugging tool, I was able to see that while the UITableView had the right height, the UITableViewWrapper inside it did not.
    – Mic Fok
    Nov 12, 2014 at 8:12
  • Perfect. This fixed the bug for me, in XCode 6.1. None of the other suggestions in this StackOverflow page made any difference. I had a UITableView within a UIView, and it WAS the first subview. Dragging it to become the 2nd subview fixed it perfectly. (If anyone needs me, I'll be in the pub.) Dec 10, 2014 at 13:50
  • Thank you! This also works if you have a table view controller within a container. Moving the container so that its not the first in the parent's view removes the gap at the top of the table view. Jan 21, 2015 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.