2

I want to display, on screen, the elapsed time since some event. I have a member variable

NSDate *_startTime;

I allocate it (and initiate a timer) like so:

_startTime = [NSDate date];
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(clock) userInfo:nil repeats:YES];

My clock function gets called fine but when I attempt to find the elapsed time I get a crash with no real way of determining what happens; I simple get EXC_BAD_ACCESS. Below is how I attempt to get the elapsed time since _startDate which throws the exception:

NSTimeInterval secondsElapsed = [_startTime timeIntervalSinceNow];

It crashes on this line - I have looked around and this seems to be the correct syntaax, what is happening here?

Chris
  • 26,744
  • 48
  • 193
  • 345

4 Answers4

2

You probably need to retain your _startTime, otherwise it gets autoreleased. (Of course, once you retain it, you are responsible for releasing it later.)

Arkku
  • 41,011
  • 10
  • 62
  • 84
2

Unless you're using ARC, you need to have ownership of the NSDate object that you're storing in _startTime. +[NSDate date] returns an object you don't own, and it is likely to have been deallocated and therefore to be invalid by the time you get around to sending it timeIntervalSinceNow.

You can create an owned NSDate like so:

// By default, NSDates are initialized with the current date
_startTime = [[NSDate alloc] init];

or by explicitly taking ownership of the return value of +date:

_startTime = [[NSDate date] retain];

They are equivalent in effect.

Even better (assuming you have a property defined for _startTime (which you should)) would be using the setter:

[self setStartTime:[NSDate date]];

With the property defined as retaining, this will handle the memory correctly.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • Thanks - P.s. how do I output the interval as a time i.e. 01:30 – Chris Jan 24 '12 at 21:23
  • P.p.s why should I define a property for internal member variables? – Chris Jan 24 '12 at 21:25
  • An `NSTimeInterval` represents seconds; there are 60 seconds in a minute. Use the division and modulus operators, or the `ldiv()` function. There are a number of questions on SO for that. – jscs Jan 24 '12 at 21:26
  • Why define a property? It makes the memory management much easier. It's possible to do without it. It's also possible to declare the property in an "internal" class extension. – jscs Jan 24 '12 at 21:29
0

You didn't retain _startTime, so it may have been deallocated by the time your timer fires.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
0

[NSDate date] will return an autoreleased object. It will be deallocated once out of scope. If you want to use it in your 'clock' function you will need to retain it.

NSIntegerMax
  • 542
  • 2
  • 5