30

I've created an extremely simple demo app to test the functionality of automaticallyAdjustsScrollViewInsets, but the last cell of the tableView is covered by my tab bar.

My AppDelegate code:

UITabBarController *tabControl = [[UITabBarController alloc] init];
tabControl.tabBar.translucent = YES;
testViewController *test = [[testViewController alloc] init];
[tabControl setViewControllers:@[test]];

[self.window setRootViewController:tabControl];

My testViewController (subclass of UITableViewController) Code:

- (void)viewDidLoad
{
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = YES;
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
self.tableView.dataSource = self;
self.tableView.scrollIndicatorInsets = self.tableView.contentInset;
//[self.view addSubview:self.tableView];

// Do any additional setup after loading the view.
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@""];
cell.textLabel.text = @"test";
return cell;
}

Is this a bug in iOS 7? If not, what did I do wrong?

Pang
  • 8,605
  • 144
  • 77
  • 113
danielmhanover
  • 2,884
  • 3
  • 32
  • 50

5 Answers5

56

I think that automaticallyAdjustsScrollViewInsets only works when your controllers view is a UIScrollView (a table view is one).

You're problem seems to be that your controller's view is a regular UIView and your UITableView is just a subview, so you'll have to either:

  • Make the table view the "root" view.

  • Adjust insets manually:

    UIEdgeInsets insets = UIEdgeInsetsMake(controller.topLayoutGuide.length,
                                           0.0,
                                           controller.bottomLayoutGuide.length,
                                           0.0);
    scrollView.contentInset = insets;
    

Edit:

Seems like the SDK is capable of adjusting some scroll views despite not being the controller's root view.

So far It works with UIScrollView's and UIWebView's scrollView when they are the subview at index 0.

Anyway this may change in future iOS releases, so you're safer adjusting insets yourself.

Rivera
  • 10,182
  • 3
  • 49
  • 96
  • 24
    I found out that it only works if there's a scrollview at index 0 of the viewcontroller's view subviews – Thomas Keuleers Mar 06 '14 at 06:38
  • Just confirmed that now. It is interesting with `UIWebView`'s as the scroll view is even deeper in the view hierarchy. – Rivera Mar 06 '14 at 06:53
  • +1 for the index 0 bit; helped me with an issue I was having with a web view not being adjusted. – Sixten Otto Apr 11 '14 at 16:52
  • Can't believe that 0 index thing. The amount of times I've had problems with this setting, to now find out it was something as stupid as that. Apple really need to warn you about this limitation. Anyway, I can confirm this also works on a UICollectionView. – Mark Bridges Sep 13 '15 at 20:37
  • 2
    What is more, I found out that if you have more than one scroll view in your view hierarchy (even if only one is installed at the moment), it does not work even if the scroll view is at index 0 in subviews. It only worked when I completely removed the other scroll views from storyboard. So this property is total mess for me... – manicaesar Nov 19 '15 at 21:34
  • 2
    On iOS 11, instead of insetting each child controller's scroll view, you can set `additionalSafeAreaInsets` on the parent (tab bar controller), and all the children will inherit it – beebcon Oct 24 '17 at 20:54
21

Your view controller must be directly on a UINavigaitonController's stack for automaticallyAdjustsScrollViewInsets to work (i.e. not a child view controller)

If it is a child view controller of another view controller which is on the navigation stack, you can instead set automaticallyAdjustsScrollViewInsets = NO on the parent. Alternatively you can do this:

self.parentViewController.automaticallyAdjustsScrollViewInsets = NO;
Robert
  • 35,442
  • 34
  • 158
  • 205
  • This answer helped me. In my case, the view controller which managed the table view was added to its parent using `addChildViewController`. Setting `self.automaticallyAdjustsScrollViewInsets = NO;` on the child was not enough. You have to set it on the parent too because it seems to recursively drill down and locate all scroll views to automatically set its insets. – Pwner Jan 06 '15 at 20:16
17

I just solved this issue with iOS 11 and swift 4, my current problem was that iOS11 has a new property to validate the insets when a ScrollView does exist, that one is contentInsetAdjustmentBehavior which is a ScrollView's property and the default property is automatic so my code was:

if #available(iOS 11, *) {
    myScroll.contentInsetAdjustmentBehavior = .never
} else {
    self.automaticallyAdjustsScrollViewInsets = false
}

I hope this solve your problems too...

DariusV
  • 1,739
  • 11
  • 19
  • what is `myScroll` here? – Alexey Strakh Dec 08 '17 at 10:37
  • It would be a simple scrollview or a tableview, collectionview... look at this https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior – DariusV Dec 08 '17 at 16:20
  • I was just wondering what happened to `automaticallyAdjustsScrollViewInsets` in iOS 11.. thanks! – carlodonz Jan 09 '18 at 00:12
  • It was just deprecated, surely it is because it makes more sense to handle the Scroll's behavior from itself instead of a ViewController's property – DariusV Jan 13 '18 at 01:32
2

I have this hierarchy:

  1. custom navigationcontroller contains custom tabbarcontroller

  2. custom tabbarcontroller contains several controllers

  3. these controllers contains subviews and one of them contains a subclass of uiscrollview.

I had to set automaticallyAdjustsScrollViewInsets to NO

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    self.automaticallyAdjustsScrollViewInsets = NO;

in the custom tabbarcontroller. Other controllers in the hierarchy do not have any impact on the nested scroll view's behavior.

Vladimír Slavík
  • 1,455
  • 1
  • 16
  • 30
2

I was having the same issue, a Table View with unwanted top padding.

All answers say to fix by setting automaticallyAdjustsScrollViewInsets = NO, but that was not eliminating the padding for me.

Similar to the other answers here, these directions need to be tweaked slightly if you're using a non-standard view hierarchy.

I had a UIViewController with an embedded UITableViewController. It was not working to set automaticallyAdjustsScrollViewInsets on the Table View Controller.

Instead, I set automaticallyAdjustsScrollViewInsets = NO on the parent UIViewController that was embedding my Table View Controller. That successfully eliminated the padding on the Table View.

pkamb
  • 26,648
  • 20
  • 124
  • 157