14

I added a method to make the scroll view to scroll to top of it. This is working as expected in iOS10. But when I upgraded to iOS11 with Xcode 9, it is not working. Is there anything that am missing respective to iOS11.
Below code was working:

[self setContentOffset:CGPointZero animated:YES];

Updating question after comment from OP (UPDATE)

I find the reason why setContentOffset:animated is not working, I use UITableView and I make some custom cell in my tableview, tableview has a property "estimatedRowHeight" , we should make this property equal "0", I guess when iOS11 calculate it's content size it will use "estimatedRowHeight", if we don't set this property , it will use system default.

This is very useful and should be more visible

Reinier Melian
  • 20,519
  • 3
  • 38
  • 55
Jason Liu
  • 151
  • 1
  • 1
  • 5

7 Answers7

32

You have to do

self.view.layoutIfNeeded()

before setContentOffset. It updates the contentSize of UIScrollView and then contentOffset is available.

Yusuke
  • 429
  • 4
  • 4
  • Thanks a lot! This was the only answer that actually helped me. It was happening when reloading the data in UITableView and then trying to setContentOffset after this accordingly. – RadioLog Jan 14 '20 at 10:24
  • Fantastic - thanks working for me in iOS 16 - the only solution that worked for me. – David H May 11 '23 at 17:55
14

(SWIFT 4) I had a similar problem, the problem was the animated : true. So, you can try by doing this manually:

view.layoutIfNeeded()
UIView.animate(withDuration: 0.2) {
   self.scroll.setContentOffset(.zero, animated: false)
}

Hope it helps. It fixed for me

Pablo Blanco
  • 679
  • 8
  • 14
9

try this

dispatch_async(dispatch_get_main_queue(), ^{
    [UIView animateWithDuration:.25 animations:^{
        [self setContentOffset:CGPointZero animated:YES];
    }];
});
R. Mohan
  • 2,182
  • 17
  • 30
  • i edited the code, try this. In that simply added the the code inside main thread. – R. Mohan Oct 10 '17 at 07:33
  • oh no, it doesn't work, build in Xcode9 and run in iOS11. – Jason Liu Oct 10 '17 at 07:53
  • remove that UIView block and try it once. – R. Mohan Oct 10 '17 at 07:54
  • not work, all answers scrollview can scroll but cant scroll to desired position. – Jason Liu Oct 10 '17 at 08:04
  • I am so sorry, I try it in demo, it work well, but in my project it doesn't work, so I guess any class influence the method use, let me fix it. – Jason Liu Oct 10 '17 at 08:28
  • Its ok. Check which is affecting that. – R. Mohan Oct 10 '17 at 09:06
  • 10
    I find the reason why setContentOffset:animated is not working, I use UITableView and I make some custom cell in my tableview, tableview has a property "estimatedRowHeight" , we should make this property equal "0", I guess when iOS11 calculate it's content size it will use "estimatedRowHeight", if we don't set this property , it will use system default. – Jason Liu Oct 11 '17 at 02:24
  • 2
    @JasonLiu please put this as an answer. That's twice the default estimatedRowHeight has bitten me now! – Airsource Ltd Mar 07 '18 at 15:21
7

Setting estimatedRowHeight = 0, estimatedSectionHeaderHeight = 0, estimatedSectionFooterHeight = 0 for the scrollview solved the issue. whenever the content offset is changed, the heights of rows, header and footers of each section is calculated by the UIKit to scroll to the new offset. estimatedRowHeight, estimatedSectionHeaderHeight, estimatedSectionFooterHeight will be -1 by default

2

The way to fix this (for my app at least) is to add "beginUpdates" and "endUpdates" to the UITableView and to choose "animated:NO" like this:

[mySuperbTableView beginUpdates];
[mySuperbTableView setContentOffset:CGpointMake(0,0) animated:NO];
[mySuperbTableView endUpdates];

you can set the CGPoint to anything you need. ;-)

Take care of doing any change to your datasource AFTER calling this update to the UITableView, otherwise it will crash !

Thanks to Pavithra Pavi who answer this correctly in another post.

Edit : OK, it does not work all the time. A better solution (if you choose to not animate the tableview) is to set table.estimatedRowHeight = 0;

in your delegate.

it seems to fix the behavior of setContentOffset:animated:NO.

Chrysotribax
  • 789
  • 1
  • 9
  • 17
  • Thanks that fixed my problems! Note: I also had to set table.estimatedSectionFooterHeight = 0 and table.estimatedSectionHeaderHeight = 0 to work in all cases – Markus Apr 30 '18 at 13:03
2

Try this

if tableView.numberOfRows(inSection: 0) > 0 {
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
}
mishimay
  • 4,237
  • 1
  • 27
  • 23
1

As @Alejandro mentioned before, iOS 11 really has problems with setContentOffset and animation.

I found out how to make it work:

Swift 3, 4:

if #available(iOS 11.0, *) {
     let offset = CGPoint(x: -scrollView.adjustedContentInset.left, y: -scrollView.adjustedContentInset.top)
     scrollView.setContentOffset(offset, animated: false)
} else {
     let offset = CGPoint(x: -scrollView.contentInset.left, y: -scrollView.contentInset.top)
     scrollView.setContentOffset(offset, animated: false)
}
atereshkov
  • 4,311
  • 1
  • 38
  • 49