In my table view I have to scroll to the top. But I cannot guarantee that the first object is going to be section 0, row 0. May be that my table view will start from section number 5.
So I get an exception, when I call:
[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
Is there another way to scroll to the top of table view?
UITableView is a subclass of UIScrollView, so you can also use:
[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
Or
[mainTableView setContentOffset:CGPointZero animated:YES];
And in Swift:
mainTableView.setContentOffset(CGPointZero, animated:true)
And in Swift 3 & above:
mainTableView.setContentOffset(.zero, animated: true)
Note: This answer isn't valid for iOS 11 and later.
I prefer
[mainTableView setContentOffset:CGPointZero animated:YES];
If you have a top inset on your table view, you have to subtract it:
[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];
Possible Actions:
1
func scrollToFirstRow() {
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}
2
func scrollToLastRow() {
let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}
3
func scrollToSelectedRow() {
let selectedRows = self.tableView.indexPathsForSelectedRows
if let selectedRow = selectedRows?[0] as? NSIndexPath {
self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
}
}
4
func scrollToHeader() {
self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}
5
func scrollToTop(){
self.tableView.setContentOffset(CGPointMake(0, UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}
Disable Scroll To Top:
func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
for subview in view.subviews {
if let scrollView = subview as? UIScrollView {
(scrollView as UIScrollView).scrollsToTop = false
}
self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
}
}
Modify and use it as per requirement.
Swift 4
func scrollToFirstRow() {
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
It's better to not use NSIndexPath (empty table), nor assume that top point is CGPointZero (content insets), that's what I use -
[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];
Hope this helps.
Swift 4:
This works very well:
//self.tableView.reloadData() if you want to use this line remember to put it before
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
DONT USE
tableView.setContentOffset(.zero, animated: true)
It can sometimes set the offset improperly. For example, in my case, the cell was actually slightly above the view with safe area insets. Not good.
INSTEAD USE
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
On iOS 11, use adjustedContentInset to correctly scroll to top for both cases when the in-call status bar is visible or not.
if (#available(iOS 11.0, *)) {
[tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}
Swift:
if #available(iOS 11.0, *) {
tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}
I've encountered an issue calling trying some of the methods on an empty tableView. Here's another option for Swift 4 that handles empty tableviews.
extension UITableView {
func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
}
func scrollToTop(animated: Bool) {
let indexPath = IndexPath(row: 0, section: 0)
if self.hasRowAtIndexPath(indexPath: indexPath) {
self.scrollToRow(at: indexPath, at: .top, animated: animated)
}
}
}
Usage:
// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false
For tables that have a contentInset, setting the content offset to CGPointZero will not work. It'll scroll to the content top vs. scrolling to the table top.
Taking content inset into account produces this instead:
[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];
This code let's you scroll a specific section to top
CGRect cellRect = [tableinstance rectForSection:section];
CGPoint origin = [tableinstacne convertPoint:cellRect.origin
fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, origin.y)];
Swift 5, iOS 13
I know this question already has a lot of answers but from my experience this method always works:
let last = IndexPath(row: someArray.count - 1, section: 0)
tableView.scrollToRow(at: last, at: .bottom, animated: true)
And this is especially true if you're working with animations (like keyboard) or certain async tasks—the other answers will often scroll to the almost bottom. If for some reason this doesn't get you all the way to the bottom, it's almost certainly because of a competing animation so the workaround is to dispatch this animation to the end of the main queue:
DispatchQueue.main.async {
let last = IndexPath(row: self.someArray.count - 1, section: 0)
self.tableView.scrollToRow(at: last, at: .bottom, animated: true)
}
This may seem redundant since you're already on the main queue but it's not because it serializes the animations.
Swift:
tableView.setContentOffset(CGPointZero, animated: true)
Swift 3
tableView.setContentOffset(CGPoint.zero, animated: true)
if tableView.setContentOffset don't work.
Use:
tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()
Since my tableView is full of all kinds of insets, this was the only thing that worked well:
Swift 3
if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}
Swift 2
if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}
Adding on to what's already been said, you can create a extension (Swift) or category (Objective C) to make this easier in the future:
Swift:
extension UITableView {
func scrollToTop(animated: Bool) {
setContentOffset(CGPointZero, animated: animated)
}
}
Any time you want to scroll any given tableView to the top you can call the following code:
tableView.scrollToTop(animated: true)
I prefer the following, as it takes into account an inset. If there is no inset, it will still scroll to the top as the inset will be 0.
tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
Swift :
if you don't have tableView header :
tableView.setContentOffset(CGPointMake(0, UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
if so :
tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
In Swift 5 , Thanks #Adrian's answer a lot
extension UITableView{
func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
}
func scrollToTop(_ animated: Bool = false) {
let indexPath = IndexPath(row: 0, section: 0)
if hasRowAtIndexPath(indexPath: indexPath) {
scrollToRow(at: indexPath, at: .top, animated: animated)
}
}
}
Usage:
tableView.scrollToTop()
Here's what I use to work correctly on iOS 11:
extension UIScrollView {
func scrollToTop(animated: Bool) {
var offset = contentOffset
if #available(iOS 11, *) {
offset.y = -adjustedContentInset.top
} else {
offset.y = -contentInset.top
}
setContentOffset(offset, animated: animated)
}
}
using contentOffset is not the right way. this would be better as it is table view's natural way
tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)
This was the only code snippet that worked for me
Swift 4:
tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)
P.S. 70 is the height of my header and table view cell
func scrollToTop() {
NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
[tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
call this function wherever you want UITableView scroll to top
Swift 4 via extension, handles empty table view:
extension UITableView {
func scrollToTop(animated: Bool) {
self.setContentOffset(CGPoint.zero, animated: animated);
}
}
I use tabBarController and i have a few section in my tableview at every tab, so this is best solution for me.
extension UITableView {
func scrollToTop(){
for index in 0...numberOfSections - 1 {
if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
break
}
if index == numberOfSections - 1 {
setContentOffset(.zero, animated: true)
break
}
}
}
}
I had to add the multiply by -1 * to the sum of the status bar and the navigation bar, because it was going that height off the screen,
self.tableView.setContentOffset(CGPointMake(0 , -1 *
(self.navigationController!.navigationBar.height +
UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)
in swift
your row = selectioncellRowNumber
your section if you have = selectionNumber if you dont have set is to zero
//UITableViewScrollPosition.Middle or Bottom or Top
var lastIndex = NSIndexPath(forRow: selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
Here Is The Code To ScrollTableView To Top Programatically
Swift:
self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)
In Swift-3 :
self.tableView.setContentOffset(CGPoint.zero, animated: true)
If you need use Objective-C or you still in love:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Solution with scrollToRow which fixes the problem for empty TableView (needs for search).
import UIKit
extension UITableView {
public func scrollToTop(animated: Bool = false) {
if numberOfRows(inSection: 0) > 0 {
scrollToRow(
at: .init(row: 0, section: 0),
at: .top,
animated: animated
)
}
}
}
Related
I currently have a login and signup buttons labeled as 1 and 2. And underneath that, I have a collectionView with two cells (one for the login UI and one for register UI). When I click on the signup button(Label 2), I want to move the collectionView to the next cell.
I tried using the scrollToItem, but it does not do anything. Anyone know why?
#objc private func didTapRegisterButton() {
let i = IndexPath(item: 1, section: 0)
self.onboardingCollectionView.scrollToItem(at: i, at: .right, animated: true)
}
Figured it out. My collectionView had isPagingEnabled property as true. The scrollToItem doesn't work if that is set to true.
If you want to scroll between two cells on button click then first you need to uncheck(disable) Scrolling Enabled property and check(enable) Paging Enabled property of collectionView. (With this approach user can't scroll manually with swipe)
On button first action,
if self.currentIndexPath == 0 {
return
} else {
self.currentIndexPath += 1
self.yourCollectionView.scrollToItem(at: IndexPath(row: self.currentVisibleIndexPath, section: 0), at: .centeredHorizontally, animated: true)
}
On button second action,
if self.currentIndexPath == 1 {
self.currentIndexPath -= 1
self.yourCollectionView.scrollToItem(at: IndexPath(row: self.currentVisibleIndexPath, section: 0), at: .centeredHorizontally, animated: true)
} else {
return
}
And declare global variable
var currentIndexPath: Int = 0
I'm using a collection view, UICollectionView, and it works absolutely great...except that I cannot scroll to any particular item. It seems to always scroll to the "middle" is my best guess. In any case, whatever I send to scrollToItem seems to have no effect on the scrolling. I've put it in various locations throughout my view controller but with no success.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let lastIndex = IndexPath(row: messages.count-1, section: 0)
self.messagesView.scrollToItem(at: lastIndex, at: .bottom, animated: true)
}
UICollection View has bug in iOS 14 with scrollToItem. In iOS 14 it will only work if collection view paging will be desable.
So i got a solution if we have to scroll with both manual and programatically.
Specially for iOS 14 and above
self.collView.isPagingEnabled = false
self.collView.scrollToItem(at: IndexPath(item: scrollingIndex, section: 0), at: .left, animated: true)
self.collView.isPagingEnabled = true
You could try putting the scrolling code in viewDidLayoutSubviews which should get called after all table cells are loaded, which means your messages.count should work. Also, make sure you only have a single section in your collection view.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.scrollToBottom()
}
func scrollToBottom() {
DispatchQueue.main.async {
let lastIndex = IndexPath(item: messages.count-1, section: 0)
self.messagesView.scrollToItem(at: lastIndex, at: .bottom, animated: true)
}
}
Swift 5 / iOS 15
I was facing the same problem, so I tried this one-line code and get it done.
// here we slect the required cell instead of directly scrolling to the item and both work same.
self.collectionView.selectItem(at: IndexPath(row: self.index, section: 0), animated: true, scrollPosition: .left)
This is what worked for me, in case you want paging enabled:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.isPagingEnabled = false
collectionView.scrollToItem(
at: IndexPath(item: 1, section: 0),
at: .centeredVertically,
animated: false
)
collectionView.isPagingEnabled = true
}
I'm writing a table view where rows are added upon user interaction. The general behavior is simply to add a single row, then scroll to the end of the table.
This was working perfectly fine before iOS11, but now the scrolling always jumps from the top of the table instead of smoothly scrolling.
Here's the code that has to do with adding new rows:
func updateLastRow() {
DispatchQueue.main.async {
let lastIndexPath = IndexPath(row: self.currentSteps.count - 1, section: 0)
self.tableView.beginUpdates()
self.tableView.insertRows(at: [lastIndexPath], with: .none)
self.adjustInsets()
self.tableView.endUpdates()
self.tableView.scrollToRow(at: lastIndexPath,
at: UITableViewScrollPosition.none,
animated: true)
}
}
And
func adjustInsets() {
let tableHeight = self.tableView.frame.height + 20
let table40pcHeight = tableHeight / 100 * 40
let bottomInset = tableHeight - table40pcHeight - self.loadedCells.last!.frame.height
let topInset = table40pcHeight
self.tableView.contentInset = UIEdgeInsetsMake(topInset, 0, bottomInset, 0)
}
I'm confident the error lies within the fact that multiple UI updates are pushed at the same time (adding row and recalculating edge insets), and tried chaining these functions with separate CATransaction objects, but that completely messes up asynchronous completion blocks defined elsewhere in the code which update some of the cell's UI elements.
So any help would be appreciated :)
I managed to fix the issue by simply just calling self.tableView.layoutIfNeeded() before adjusting the insets:
func updateLastRow() {
DispatchQueue.main.async {
let lastIndexPath = IndexPath(row: self.currentSteps.count - 1, section: 0)
self.tableView.beginUpdates()
self.tableView.insertRows(at: [lastIndexPath], with: .none)
self.tableView.endUpdates()
self.tableView.layoutIfNeeded()
self.adjustInsets()
self.tableView.scrollToRow(at: lastIndexPath,
at: UITableViewScrollPosition.bottom,
animated: true)
}
}
Make sure that you are respecting the Safe Areas.
For more details, check: https://developer.apple.com/ios/update-apps-for-iphone-x/
I have a UITableView with cells that are dynamically updated. Everything works fine apart from when tableview.reload is called (see below) to refresh the cells in the table I would like the table to scroll to the bottom to show the new entries.
- (void)reloadTable:(NSNotification *)notification {
NSLog(#"RELOAD TABLE ...");
[customTableView reloadData];
// Scroll to bottom of UITable here ....
}
I was planning to use scrollToRowAtIndexPath:atScrollPosition:animated: but then noticed that I don't have access to an indexPath.
Does anyone know how to do this, or of a delegate callback that I could use?
Use:
NSIndexPath* ipath = [NSIndexPath indexPathForRow: cells_count-1 inSection: sections_count-1];
[tableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated: YES];
Or you can specify the section index manually (If one section => index=0).
Another solution is to flip the table vertically, and flip each cell vertically:
Apply the transform to the UITableView when initializing:
tableview.transform = CGAffineTransformMakeScale(1, -1);
and in cellForRowAtIndexPath:
cell.transform = CGAffineTransformMakeScale(1, -1);
This way you don't need workarounds for scrolling issues, but you will need to think a little harder about contentInsets/contentOffsets and header/footer interactions.
-(void)scrollToBottom{
[self.tableView scrollRectToVisible:CGRectMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height, self.tableView.bounds.size.width, self.tableView.bounds.size.height) animated:YES];
}
//In swift
var iPath = NSIndexPath(forRow: self.tableView.numberOfRowsInSection(0)-1,
inSection: self.tableView.numberOfSections()-1)
self.tableView.scrollToRowAtIndexPath(iPath,
atScrollPosition: UITableViewScrollPosition.Bottom,
animated: true)
Swift 3
For all the folks here trying to figure out how to solve this problem the key is to call the .layoutIfNeeded() method after .reloadData() :
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.height), animated: false)
I was working with multiple sections in UITableView and it worked well.
Fot Swift 5
extension UITableView {
func scrollToBottom(animated: Bool = true) {
let section = self.numberOfSections
if section > 0 {
let row = self.numberOfRows(inSection: section - 1)
if row > 0 {
self.scrollToRow(at: IndexPath(row: row-1, section: section-1), at: .bottom, animated: animated)
}
}
}
}
As this is something you might want to use really often, I suggest that you create a class extension on UITableView :
extension UITableView {
func scrollToBottom(animated: Bool = true) {
let section = self.numberOfSections
if section > 0 {
let row = self.numberOfRowsInSection(section - 1)
if row > 0 {
self.scrollToRowAtIndexPath(NSIndexPath(forRow: row - 1, inSection: section - 1), atScrollPosition: .Bottom, animated: animated)
}
}
}
}
This is another solution, worked well in my case, when cell height is big.
- (void)scrollToBottom
{
CGPoint bottomOffset = CGPointMake(0, _bubbleTable.contentSize.height - _bubbleTable.bounds.size.height);
if ( bottomOffset.y > 0 ) {
[_bubbleTable setContentOffset:bottomOffset animated:YES];
}
}
extension is better to be done on UIScrollView instead of UITableView, this way it works on scrollView, tableView, collectionView (vertical), UIWebView (inner scroll view), etc
public extension UIScrollView {
public func scrollToBottom(animated animated: Bool) {
let rect = CGRectMake(0, contentSize.height - bounds.size.height, bounds.size.width, bounds.size.height)
scrollRectToVisible(rect, animated: animated)
}
}
Swift 5
func scrollToBottom() {
let section = self.tableView.numberOfSections
let row = self.tableView.numberOfRows(inSection: self.tableView.numberOfSections - 1) - 1;
guard (section > 0) && (row > 0) else{ // check bounds
return
}
let indexPath = IndexPath(row: row-1, section: section-1)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
I dont agree that we should user cells_count,sections_count,self.dateSource.countand so on, Instead, the delegate will be better.
This is the best way.
- (void)scrollToBottom
{
CGFloat yOffset = 0;
if (self.tableView.contentSize.height > self.tableView.bounds.size.height) {
yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
}
[self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO];
}
try this code, It may help you:
self.tableView.reloadData()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: {
let indexPath = IndexPath(row: self.dateSource.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true)
})
In IOS6 I have the following code to scroll to the top of a UITableView
[tableView setContentOffset:CGPointZero animated:YES];
In IOS7 this doesn't work anymore. The table view isn't scrolled completely to the top (but almost).
In iOS7, whole screen UITableView and UIScrollView components, by default, adjust content and scroll indicator insets to just make everything work. However, as you've noticed CGPointZero no longer represents the content offset that takes you to the visual "top".
Use this instead:
self.tableView.contentOffset = CGPointMake(0, 0 - self.tableView.contentInset.top);
Here, you don't have to worry about if you have sections or rows. You also don't tell the Table View to target the first row, and then wonder why it didn't show all of your very tall table header view, etc.
Try this:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
Based on the accepted answer from #Markus Johansson, here is the Swift code version:
func scrollToTop() {
if (self.tableView.numberOfSections > 0 ) {
let top = NSIndexPath(row: Foundation.NSNotFound, section: 0)
self.tableView.scrollToRow(at: top as IndexPath, at: .top, animated: true);
}
}
By the help from some other answers here I managed to get it working. To avoid a crash I must first check that there are some sections. NsNotFound can be used as a row index if the first section has no rows. Hopefully this should be a generic function to be placed in a UITableViewController:
-(void) scrollToTop
{
if ([self numberOfSectionsInTableView:self.tableView] > 0)
{
NSIndexPath* top = [NSIndexPath indexPathForRow:NSNotFound inSection:0];
[self.tableView scrollToRowAtIndexPath:top atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
var indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.sampleTableView.scrollToRowAtIndexPath(indexPath,
atScrollPosition: UITableViewScrollPosition.Top, animated: true)
or
self.sampleTableView.setContentOffset(CGPoint.zero, animated:false)
float systemVersion= [[[UIDevice currentDevice] systemVersion] floatValue];
if(systemVersion >= 7.0f)
{
self.edgesForExtendedLayout=UIRectEdgeNone;
}
Try this code in viewDidLoad() method.
Here is idStar's answer in updated Swift 3 syntax:
self.tableView.contentOffset = CGPoint(x: 0, y: 0 - self.tableView.contentInset.top)
With animation:
self.tableView.setContentOffset(CGPoint(x: 0, y: 0 - self.tableView.contentInset.top), animated: true)
Swift 3
If you have table view headers CGPointZero may not work for you, but this always does the trick to scroll to top.
self.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: false)
you can still use scrollToRowAtIndexPath: for the purpose
I realize this has been answered but I just wanted to give another option:
CGRect frame = {{0, 0},{1, 1}};
[self.tableView scrollRectToVisible:frame animated:YES];
This always guarantees the UITableView will scroll to the top. The accepted answer:
NSIndexPath* top = [NSIndexPath indexPathForRow:NSNotFound inSection:0];
[self.tableView scrollToRowAtIndexPath:top atScrollPosition:UITableViewScrollPositionTop animated:YES];
was not working for me because I was scrolling to a tableHeaderView and not a cell.
Using scrollRectToVisible works on iOS 6 and 7.
Swift 4 UITableViewExtension:
func scrollToTop(animated: Bool) {
if numberOfSections > 0 {
let topIndexPath = IndexPath(row: NSNotFound, section: 0)
scrollToRow(at: topIndexPath, at: .top, animated: animated)
}
}
in swift I used:
self.tableView.setContentOffset(CGPointMake(0, 0), animated: true)
but #Alvin George's works great