Search code examples
iosobjective-cuitableviewios7uiscrollview

UITableView scrollViewDidScroll fired on animation


So most of the problems people have with this particular event is to have scrollViewDidScroll fire when there is animation happening. My case is just the opposite. I feel that scrollViewDidScroll should NOT be firing in my case.

Let me further explain.

I am animating things in scrollViewDidScroll and this was working perfectly until I moved UITableView into a UIView class.

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
   // Animation code here.
   NSLog(@"scrollViewDidScroll");
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
   NSLog(@"scrollViewDidEndDecelerating");
   NSArray *indexPaths = [_myTableView indexPathsForVisibleRows];
   [_myTableView scrollToRowAtIndexPath:[indexPaths objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}


What this provides is a smooth scrolling experience that snaps back to a previous table row. The console can verify that scrollViewDidScroll event is firing because of scrollToRowAtIndexPath.

Console:

2014-03-31 22:21:43.346 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.379 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.429 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.462 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.479 Project[45843:a0b] scrollViewDidEndDecelerating
2014-03-31 22:21:43.496 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.513 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.529 Project[45843:a0b] scrollViewDidScroll

Onto the questions:

1. How can I ensure that the event scrollViewDidScroll only fires due to user interaction and not automation from code?

2. Is there another method that provides the same functionality as scrollToRowAtIndexPath without triggering scrollViewDidScroll?


Solution

  • I know this is a very old question. I just have been in a similar situation that I need to run some code only when the user is scrolling but not when I call scrollToRowAtIndexPath. I have found an easier solution for this using the scrollView variables dragging and decelerating.

    we have 3 cases of scrolling here.

    1. user is dragging
    2. user just ended dragging and the tableview is decelrating
    3. programmatically called scrollForRowAtIndexPath:

    All of the cases above will trigger scrollViewDidScroll: but

    1. user is dragging dragging is True and decelerating is False
    2. user just ended dragging and the tableview is decelrating dragging is False and decelerating is True
    3. programmatically called scrollForRowAtIndexPath: dragging is False and decelerating is False

    So your code will be like something like this:

    - (void) scrollViewDidScroll:(UIScrollView *)scrollView {
        if (scrollView.dragging)
         {
           // Do what you want when user is dragging
         } else if (scrollView.decelerating) 
         {
           // Do what you want when table is decelerating after finished dragging
         } else 
         {
           // Do what you want when table is scrolling programmatically.
         }
    }
    

    Or if you want to just distinguish the scrolling progammatically

    - (void) scrollViewDidScroll:(UIScrollView *)scrollView {
        if (scrollView.dragging || scrollView.decelerating)
         {
           // Scrolling by the user
         } else 
         {
           // Scrolling by the code
         }
    }