UIScrollView & setContentOffset random scrolling on iOS 4

We encountered a nasty bug with UIScrollView while porting app to iOS 4. The following code worked just fine on old iPhone versions:

 
// Update view with new content
[self updateContent:...]

// We want the view to be on top every time the it is shown
[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

// And set the correct size to enable scrolling.
// contentHeight is updated when setting the content of subviews.
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, contentheight)];

No problems. But on iOS 4 the UIScrollView decided to do something fancy and scroll to random position depending on where it was left when the view was hidden the last time. After spending expensive manpower to solve the issue by trying numerous ways to tell the scrollView to go to top using setContentOffset, the final solution was simple yet very different what one might think: to fix this we had to set the contentSize to zero before updating any of the content.

// Need to do this on iOS 4 or the view scrolls to random position
[scrollView setContentSize:CGSizeMake(0,0)];

// Update view with new content
[self updateContent:...]

// We want the view to be on top every time it is shown
[scrollView setContentOffset:CGPointMake(0,0) animated:NO];

// And set the correct size to enable scrolling.
// contentHeight is updated when setting the content of subviews.
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, contentheight)];

Hopefully there is more logical way to update scrollview’s content without being scrolled around.

6 thoughts on “UIScrollView & setContentOffset random scrolling on iOS 4

  1. Thanks. Was banging my head against the wall too long with this problem and now it is solved!

  2. I think I have a similar problem. For me the the set content offset method only works when I have a table view which fills the whole screen. When my table view has only few cells then it doesn’t work. I’m using a UITableViewController and I have a search box on top of my table view. I need to show/hide the search at certain scrolled positions. The code I currently have now is,

    – (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
    {

    CGPoint point = scrollView.contentOffset ;

    if ((point.y > 22) && (point.y 0 && point.y < 22) {
    [self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
    }

    }

  3. Thanks Mikko,

    I had a hard time tracking this down as well, and in the end the zero content size was the key.

    I had to set the content size to zero before changing any text in a UITextView under the UIScrollView, and after changing the text, setting the content size back.

  4. Thank you so much for posting this. I’m dealing with a lot of complex view scrolling and you saved me many hours of testing. Bless you!

  5. Thanks very much for that. I spent the afternoon on this bug, and this article is what gave me the solution.

    Thanks!

  6. Heh! I have this amazing bug on iOS 5.0-5.1 too but it’s fixed is iOS 6. Thank’s!

Leave a Reply

Your email address will not be published. Required fields are marked *