Detecting UIScrollView page change

Use this to detect which page is currently being shown and perform some action on page change:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    static NSInteger previousPage = 0;
    CGFloat pageWidth = scrollView.frame.size.width;
    float fractionalPage = scrollView.contentOffset.x / pageWidth;
    NSInteger page = lround(fractionalPage);
    if (previousPage != page) {
        // Page has changed, do your thing!
        // ...
        // Finally, update previous page
        previousPage = page;
    }
}

If it's acceptable for you to only react to the page change once the scrolling has completely stopped, then it would be best to do the above inside the scrollViewDidEndDecelerating: delegate method instead of the scrollViewDidScroll: method.


In paging enabled scroll view you can use scrollViewDidEndDecelerating to know when the view is settled on a page (might be the same page).

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

scrollViewDidScroll gets called on every movement. And in context of paging enabled view can be used to find when it is scrolled enough to move to next page (if dragging is stopped at that point).


How about combining two methods of UIScrollViewDelegate?

In scrollViewDidEndDragging(_:willDecelerate:), if it stops right away, we do the page calculation; if it is decelerating, we let it go and it will be caught by scrollViewDidEndDecelerating(_:).

The code is tested with XCode version 7.1.1, Swift version 2.1

class ViewController: UIViewController, UIScrollViewDelegate {

  // MARK: UIScrollViewDelegate
  func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if decelerate == false {
        let currentPage = scrollView.currentPage
        // Do something with your page update
        print("scrollViewDidEndDragging: \(currentPage)")
    }
  }

  func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    let currentPage = scrollView.currentPage
    // Do something with your page update
    print("scrollViewDidEndDecelerating: \(currentPage)")
  }

}

extension UIScrollView {
   var currentPage: Int {
      return Int((self.contentOffset.x+ (0.5*self.frame.size.width))/self.frame.width)+1
   }
}