Calling topLayoutGuide breaks scrolling altogether?

I am having weird issues with the topLayoutGuide method, which I have to use in a situation where setAutomaticallyAdjustsScrollViewInsets: doesn’t work. To narrow down the cause of the problem, I’ve created the following minimal example, which just sets up a basic table view for testing:

  1. Set up a new iOS Single View application in Xcode.
  2. Paste the following code in ViewController.m’s implementation:

  3. CoreTelephony crash
  4. Stop native web app from reloading itself upon opening on iOS
  5. UISearchBar CGContext ERROR
  6. Change UIDatePicker TextColor in iOS10
  7. Checksum Validation Failed when submitting with Xcode 5
  8. Objective-C vs PhoneGap
  9. @implementation ViewController
    
    - (void)loadView
    {
        [self setTableView:[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]];
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self setAutomaticallyAdjustsScrollViewInsets:NO]; // [*]
    }
    
    - (void)viewDidLayoutSubviews
    {
        UITableView *tableView = [self tableView];
    
        UIEdgeInsets insets = [tableView contentInset];
        // insets.top = [[self topLayoutGuide] length]; // [1]
        // insets.top = 100;                            // [2]
    
        [tableView setContentInset:insets];
        [tableView setScrollIndicatorInsets:insets];
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return 100;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    
        [[cell textLabel] setText:[NSString stringWithFormat:@"%d", [indexPath row]]];
    
        return cell;
    }
    
    @end
    

The issues that I’m having are these:

  1. If I uncomment the line marked with [1], the correct inset is applied, but scrolling the table view no longer works. When I try to scroll, the table just bounces back to the initial scroll position after I release my finger. This behaviour is also triggered by a plain call to [self topLayoutGuide], without assigning the result to anything.

  2. If I uncomment line [2] instead of [1], scrolling works. The inset of 100 pt is applied as well. But now the initial scrolling position is automatically adjusted so that the content underlaps the status bar.

([*]: This really only seems to do anything in combination with a containing navigation controller. I doesn’t seem to make a difference in this example, but I want to disable any automatic behaviour just to be sure.)

Is there anything obvious I’m doing wrong? I’m really at a loss here.

2 Solutions Collect From Internet About “Calling topLayoutGuide breaks scrolling altogether?”

This is definitely a bug in iOS 7 (doesn’t appear to be fixed in 7.1) but seems to only affect UITableViewControllers. I switched over to using a UIViewController with an embedded UITableView since I am not using static cells and don’t need any of the ‘magic’ that a UITableViewController gives you.

Once I wired up the UITableViewDataSource and UITableViewDelegate manually I was able to start using self.topLayoutGuide without messing up the tableView’s contentSize.

This was an acceptable workaround for me until Apple fixes the bug.

Same thing to me, instead of getting the topLayoutGuide, try this:

CGFloat topOffset = CGRectGetMaxY(self.refController.navigationController.navigationBar.frame);