Search code examples
iosiphoneobjective-cuiscrollviewcontentoffset

UIScrollView not scrolling to bottom in iOS 7


In this following code example self.contentView refers to the UIScrollView in question.

// Scroll to bottom.
CGPoint bottomOffset = CGPointMake(0, self.contentView.contentSize.height - 
                                   self.contentView.bounds.size.height);
if (bottomOffset.y >= 0.0)
{
    [self.contentView setContentOffset:bottomOffset animated:YES];
}

Oddly, in iOS 6 this works perfectly fine, but in iOS 7 the scroll view (assuming it has a contentSize that's vertically larger than it's frame.size.height) only scrolls to the very bottom of the bottom most subview added to the scroll view.

For example, if the following cases hold true:

self.contentView.frame.size.height == 50.0
self.contentView.contentSize.height == 100.0

aSubView.frame.origin.y == 50.0
aSubView.frame.size.height == 20.0

The scrolling code will only scroll until aSubView is visible; self.contentView.contentOffset.y == 20.0 rather than self.contentView.contentOffset.y == 50.0 which would be at the bottom of the entire scroll view.

This is (of course) occurs until programmatically another subview is added to self.contentView (via a user interaction), then everything corrects itself.

For clarity, I set breakpoints before and after the scrolling code to measure changes to self.contentView.contentOffset.

Other fun fact, if I remove animated and set the contentOffset directly it works as expected on iOS 7, but I'd prefer keeping the animation.

NOTE: Not using interface builder


Solution

  • So I figured out a pretty unsatisfying solution rather quickly by wrapping the call in an async dispatch block.

    // Scroll to bottom.
    CGPoint bottomOffset = CGPointMake(0, self.contentView.contentSize.height
                                       - self.contentView.bounds.size.height);
    if (bottomOffset.y >= 0.0)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.contentView setContentOffset:bottomOffset animated:YES];
        });
    }
    

    If anyone understands what is really causing the problem and can provide a better solution I'd gladly accept that as the answer, but for everyone else dealing with the same issue hopefully this works for you as well.