Search code examples
iosuitableviewnstimer

NSTimer to scroll UITableView is slow


I'm using NSTimer to fire a method that scrolls UITableView

self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 
                                              target:self
                                            selector:@selector(scroller)
                                            userInfo:nil
                                             repeats:YES];

-(void)scroller
{
    [self.row1TableView setContentOffset:CGPointMake(self.row1TableView.contentOffset.x, self.row1TableView.contentOffset.y - 50) animated:YES]; 
}

Problem is that the scrolling seems slow. It's closer to 1 second than .1 seconds in the interval.

What's the problem?


Solution

  • As far as I know, you can not change the default animation duration of setContentOffset:animated:. But what you can do is, setup a Core Animation display link (CADisplayLink - you can search for code samples on how to set up, but it is quite straight-forward. The class documentation should be a good place to start) and it will fire every frame, calling back a method you provide.

    Inside that callback method, you can calculate how much you want to scroll your table view (how many points per frame), and call setContentOffset:animated: with the second parameter set to NO (immediate scrolling). You should implement some sort of easing to achieve better results.

    Note: The reason for using CADisplayLink instead of NSTimer is, it is more reliable. It is what you would use in games before SpriteKit was available.

    Addendum: This blog post has some sample code on how to setup the display link and the respective callback method.

    Addendum 2: You can setup an instance variable to act as a "counter", and increment it by the ammount of time ellapsed since last frame, within each call of your callback (use properties duration and/or frameInterval). Once the counter reaches a critical value (that is, the animation has run for enough time) you can stop the display link update by calling the method:

    -[CADisplayLink invalidate].