39

I am trying to make a stop watch with NSTimer.

I gave the following code:

 nst_Timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(showTime) userInfo:nil repeats:NO];

and it is not working in milliseconds. It takes more than 1 millisecond.

Brock Woolf
  • 46,656
  • 50
  • 121
  • 144
new_programmer
  • 840
  • 3
  • 12
  • 22

1 Answers1

90

Don't use NSTimer that way. NSTimer is normally used to fire a selector at some time interval. It isn't high precision and isn't suited to what you want to do.

What you want is a High resolution timer class (using NSDate):

Output:

Total time was: 0.002027 milliseconds
Total time was: 0.000002 seconds
Total time was: 0.000000 minutes

Main:

Timer *timer = [[Timer alloc] init];

[timer startTimer];
// Do some work
[timer stopTimer];

NSLog(@"Total time was: %lf milliseconds", [timer timeElapsedInMilliseconds]);  
NSLog(@"Total time was: %lf seconds", [timer timeElapsedInSeconds]);
NSLog(@"Total time was: %lf minutes", [timer timeElapsedInMinutes]);

Edit: Added methods for -timeElapsedInMilliseconds and -timeElapsedInMinutes

Timer.h:

#import <Foundation/Foundation.h>

@interface Timer : NSObject {
    NSDate *start;
    NSDate *end;
}

- (void) startTimer;
- (void) stopTimer;
- (double) timeElapsedInSeconds;
- (double) timeElapsedInMilliseconds;
- (double) timeElapsedInMinutes;

@end

Timer.m

#import "Timer.h"

@implementation Timer

- (id) init {
    self = [super init];
    if (self != nil) {
        start = nil;
        end = nil;
    }
    return self;
}

- (void) startTimer {
    start = [NSDate date];
}

- (void) stopTimer {
    end = [NSDate date];
}

- (double) timeElapsedInSeconds {
    return [end timeIntervalSinceDate:start];
}

- (double) timeElapsedInMilliseconds {
    return [self timeElapsedInSeconds] * 1000.0f;
}

- (double) timeElapsedInMinutes {
    return [self timeElapsedInSeconds] / 60.0f;
}

@end
Brock Woolf
  • 46,656
  • 50
  • 121
  • 144
  • That was a fantastic explanation... Thank you but one prob. how to convert this double to a time format like "Hr:Sec:Min:Millsec" – new_programmer Aug 19 '10 at 08:30
  • 1
    This class does not contain a dealloc method. Won't this leak? – midas06 Apr 01 '11 at 01:40
  • 2
    If I wanted to use this class to execute a block of code repeatedly (like a repeating NSTimer), how would I do this ? – Sabobin Apr 14 '11 at 15:17
  • 1
    This answer is too ridiculously great to only have 1 (now 2) votes up. – SeniorShizzle Jul 13 '11 at 04:45
  • @new_programmer: Use NSDateFormatter – titaniumdecoy Jul 14 '11 at 18:11
  • 4
    Since ``[NSDate date]`` is autoreleased in ``startTimer`` and ``stopTimer``, nothing guarantees that these objects are released by the autorelease pool before one tries to use them later in, say, ``timeElapsedInSeconds``. You should retain them in ``startTimer`` and ``stopTimer``, and also release the previous instances there (and also in the ``dealloc`` method) to prevent memory access problems. – Tamás Aug 22 '11 at 18:48
  • @Tamás can you expand upon that a little bit? What are you referring to when you say "these objects"? The NSDates? Can you give an example of the code for startTimer and stopTimer retaining and releasing? When you say "also in the dealloc method" do you mean override the dealloc method? – zakdances Apr 09 '12 at 06:09
  • 4
    @yourfriendzak: I'm referring to the `NSDate` objects constructed in `startTimer` and `stopTimer`; they are autoreleased, hence they have a retain count of zero and they could be released by the autorelease pool any time. I would probably make `start` and `end` a `@property (nonatomic,retain)` and then use `self.start = [NSDate date]` and `self.end = [NSDate date]`. In `dealloc`, it is then required to release `start and `end` with `[start release]` and `[end release]`, by overriding the `dealloc` method (but of course one should call `dealloc` in the superclass at the end). – Tamás Apr 09 '12 at 09:46
  • 1
    I don't understand why anyone is upvoting this. Fine code, but does even come close to doing what NSTimer does. NSTimer repeatedly fires a method at a set time interval. This just tell you how long a peice of code took to execute? Am I missing something? – tybro0103 Jul 19 '12 at 02:19
  • 1
    Yes. That's all it is. It appears that is all that is wanted. – Alex Zavatone Feb 19 '13 at 16:51