0

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?

noobsmcgoobs
  • 2,716
  • 5
  • 32
  • 52
  • 0.1 here (the timer interval) is **not** the time it takes for the scrolling animation to complete -or "animation duration" (I think you can not specify that)-, but the _delay_ until the animation actually starts. – Nicolas Miari Jul 01 '15 at 05:57
  • is there any way for the animation to move quicker? – noobsmcgoobs Jul 01 '15 at 06:05
  • 1
    Did you try setting the `animated:` parameter of `setContentOffset:animated:` to `NO` ? – FormigaNinja Jul 01 '15 at 06:11
  • There is no way of changing the default animation duration as far as I know. However, as @FormigaNinja suggested, you could 'fake' the animation by calling the `setContentOffset:animated:` method with `animated:NO` every frame, and set an offset increment that matches your desired scrolling ammount per frame. However, I wouldn't use `NSTimer` for this, but `CADisplayLink` instead. – Nicolas Miari Jul 01 '15 at 06:13
  • 1
    That is, if you want a scroll speed of (say), 10 points per frame (600 points per second assuming 60 fps), you could increase the offset by just that ammount, and immediately (not animated) on each call. – Nicolas Miari Jul 01 '15 at 06:15
  • @NicolasMiari I'd accept your answer if you posted as an answer and not a comment. Thanks. – noobsmcgoobs Jul 01 '15 at 06:28

2 Answers2

1

NSTimer that calls a selector on the current threads run loop. It may not be 100% precise time-wise as it attempts to dequeue the message from the run loop and perform the selector.

Jatin Patel - JP
  • 3,725
  • 2
  • 21
  • 43
1

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].

Community
  • 1
  • 1
Nicolas Miari
  • 16,006
  • 8
  • 81
  • 189
  • In this case, it will NOT resolve the issue with timer, because the answer is suggesting you to use another approach instead of using `NSTimer`. – FormigaNinja Jul 01 '15 at 07:29
  • You add the display link to a specific run loop, like you do for timers. It would seem to depend on which run loop you add it to (I'm a bit rusty on this). There's some discussion in this question: http://stackoverflow.com/questions/2524347/cadisplaylink-stops-updating-when-uiscrollview-scrolled – Nicolas Miari Jul 01 '15 at 07:29
  • It will not resolve the issue with timer because there will be no timer; I am suggesting he uses CADisplayLink instead (which is more reliable). There might be **other** threading issues/interfere with UIKits other animations, but that's why he should experiment with to which run loop he adds the display link. – Nicolas Miari Jul 01 '15 at 07:32
  • Cool, it works. How can I get it to have a duration like I can with NSTimer, like say for 2 seconds? How can I get it to stop? – noobsmcgoobs Jul 01 '15 at 08:05
  • See my update. Invalidate display link once your custom counter reaches a value of 2.0 – Nicolas Miari Jul 01 '15 at 08:12