1

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

Awesome-o
  • 2,002
  • 1
  • 26
  • 38

4 Answers4

7

Just one line ..you can scroll to bottom.. !

[yourScrollview scrollRectToVisible:CGRectMake(yourScrollview.contentSize.width - 1, yourScrollview.contentSize.height - 1, 1, 1) animated:YES];
coder
  • 10,460
  • 17
  • 72
  • 125
AP_
  • 1,013
  • 12
  • 13
5

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.

Awesome-o
  • 2,002
  • 1
  • 26
  • 38
  • Why is it unsatisfying? Animation code should always run on the main thread and you just make sure it does with that. The intrinsic reason why you need to force that and the application doesn't automatically make it run on main thread must be related to some inner workings that probably only Apple engineers would be able to explain. – manecosta Feb 13 '14 at 20:35
  • 2
    It's unsatisfying because the code already worked without the dispatch block in iOS 6 and this code is only executed on the main thread anyway so it should work without the additional dispatch block. The fact that I have to force the program to wait until the current Runloop cycle is finish with whatever it's doing before executing this line of code displays a lack of understanding of what's really happening when the method is called. – Awesome-o Feb 13 '14 at 20:57
  • 1
    This behaviour is weird. Forcing to use the main queue solves the scrolling problems I encounter... Thanks for your help. – Vico Sep 24 '14 at 16:07
0

Disabling "Adjust Scroll View Insets" solved this for me. (Xcode 6, iOS 8)

UIScrollView Not Scrolling

Albert Bori
  • 9,832
  • 10
  • 51
  • 78
-1

You can deselecting 'Use Autolayout' in the File Inspector pane of main view within the Scroll View.This may help u. UIScrollView doesn't scroll after upgrading to iOS7 / xcode 5

Community
  • 1
  • 1
MackC
  • 352
  • 3
  • 17