Jason Liu
Jason Liu

Reputation: 161

UIScrollView setContentOffset:animated not working in iOS11

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

Upvotes: 15

Views: 19771

Answers (7)

mishimay
mishimay

Reputation: 4337

Try this

if tableView.numberOfRows(inSection: 0) > 0 {
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: false)
}

Upvotes: 2

Rahamaan Sherif
Rahamaan Sherif

Reputation: 71

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

Upvotes: 7

Pablo Blanco
Pablo Blanco

Reputation: 739

(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

Upvotes: 17

Yusuke
Yusuke

Reputation: 439

You have to do

self.view.layoutIfNeeded()

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

Upvotes: 33

Chrysotribax
Chrysotribax

Reputation: 839

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.

Upvotes: 2

atereshkov
atereshkov

Reputation: 4565

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)
}

Upvotes: 1

Mohan Ramanathan
Mohan Ramanathan

Reputation: 2209

try this

dispatch_async(dispatch_get_main_queue(), ^{
    [UIView animateWithDuration:.25 animations:^{
        [self setContentOffset:CGPointZero animated:YES];
    }];
});

Upvotes: 11

Related Questions