5

Without creating multiple NSTimer instances, how would one achieve an NSTimer to fire a specific or multiple method with different intervals in a sequence. For example method1 (0.3 sec), method2 (0.5), method3 (0.7) and so on.

I would appreciate if someone could please share any example code.

Hailei
  • 42,163
  • 6
  • 44
  • 69
Naveed Abbas
  • 1,157
  • 1
  • 14
  • 37

5 Answers5

6

I'm not sure what your final goal is with this but after reading your question I would recommend to try the following way, maybe this is what you'd look for.

you should put this code where you normally wanted to start the same NSTimer class with different intervals (what is not possible, unfortunately).

{
    // ...
    [self performSelector:@selector(method1) withObject:nil afterDelay:0.3f];
    [self performSelector:@selector(method2) withObject:nil afterDelay:0.5f];
    [self performSelector:@selector(method3) withObject:nil afterDelay:0.7f];
    // ...
}

and when need to unschedule all those selectors queued, use this code.

[NSObject cancelPreviousPerformRequestsWithTarget:self];
Naveed Abbas
  • 1,157
  • 1
  • 14
  • 37
holex
  • 23,961
  • 7
  • 62
  • 76
4

NSTimer itself does not provide that functionality, it fires either once or repeatedly at fixed intervals. You will require multiple timers to achieve this effect, or move away from NSTimer entirely.

waldrumpus
  • 2,540
  • 18
  • 44
0

i beleive you should pass current time interval to the fired selector and further handle it there. if time interval is 0.3 you call method1, 0.5 - method2, there's most likely no other way to implement this

Andrey Chernukha
  • 21,488
  • 17
  • 97
  • 161
-1

Make a wrapper to wrap the NSTimer method call like this:

- (void) CallTimerWithTimeInterval:(float) interval andSelector:(NSString *)methodName 
{
SEL selector = selectorFromString(methodName);
    [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(selector) userInfo:nil repeats:YES];
}

You can call this method and pass the interval and selector method as per your requirement.

Sehrish Khan
  • 309
  • 1
  • 2
  • 9
  • Thanks, I have used the other method. Btw if I use this method, Do I have to stop or nil the timer it creates at any stage? how would I achieve that? – Naveed Abbas Jul 18 '12 at 11:01
  • To stop the timer you need to set the `repeats` parameter to `NO`. You can do that by adding another parameter to the wrapper function. `- (void) CallTimerWithTimeInterval:(float) interval andSelector:(NSString *)methodName withRepeats:(BOOL) YESorNO`. – Sehrish Khan Jul 18 '12 at 11:38
  • Thanks for the help, just being curious whether this approach is better than the one I chose. The scenario is that I would have to call this method multiple times lets say 10 times. It will create 10 copies of NSTimer scheduled to fire on particular time. Now if middle of somewhere I wish to terminate the timers all at once, repeats NO might not help as its stopping it for re-occurrences. Once 10 copies are scheduled, how would I stop it. Make an instance variable of NSTimer and then send a nil message? – Naveed Abbas Jul 18 '12 at 12:58
  • Sorry for the delayed response. If you want to invalidate multiple timers all using a single command than this might help. http://www.iphonedevsdk.com/forum/iphone-sdk-development/26645-invalidate-multiple-nstimer.html – Sehrish Khan Jul 19 '12 at 04:19
  • If `methodName` is an `NSString` you need to use `NSSelectorFromString`, or, you need to change `methodName` to be of type `SEL`. – dreamlax Jul 21 '12 at 06:15
  • @dreamlax thank you for your advice. My mistake. I will edit my answer accordingly. – Sehrish Khan Jul 21 '12 at 11:45
-3

create an timer with selector with timeinterval = 0.1 from there in the selector method, you can check by keeping a static float variable and add 0.1 to it everytime like:

static CGFloat counter= 0;

counter+= 0.1;

then check the counter value and call ur methods..

if(0.3 == counter)
{
    [self callMethod1];
}
else if(0.5 == counter)
{
    [self callMethod2];
}
else if(0.7 == counter)
{
    [self callMethod3];
}
...
...
..
..
Saurabh Passolia
  • 8,099
  • 1
  • 26
  • 41
  • Comparing floats with == is asking for trouble because they are binary approximations of the decimal representation. – jbat100 Jul 18 '12 at 08:03
  • but we are only adding 0.1 within our code and counter values are not approximation coming out of the calculations based on undecided factors such as a timer. counter values are not dependent on timer fire interval rather than it depends on how many times method is invoked. it is like `i += 1;` so there should not be any problems. – Saurabh Passolia Jul 18 '12 at 08:08
  • 1
    Better to use an integer, increment the integer by 1 every 100 milliseconds, and use `if ((counter % 3) == 0)` etc... – dreamlax Jul 18 '12 at 08:08
  • 2
    @samfisher: Did you know that `0.2` cannot be represented in a float exactly? In binary, it is a repeating pattern 0.0011001100110011... [see here](http://stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary). – dreamlax Jul 18 '12 at 08:12
  • @samfisher I'm not talking about timer inaccuracies I'm talking about decimal number representation inaccuracies as mentioned by dreamlax. 0.1 would be something along the lines of 0.10000000000000001 or 0.99999999999999998. – jbat100 Jul 18 '12 at 08:25