I'm instantiating and scheduling a timer variable but Xcode compiler and analyzer marks my var "levelScoreTimer" with 2 warnings like "warning: unused variable 'levelScoreTimer' and "Dead store: Value stored to 'levelScoreTimer' during its initialization is never read". What is wrong with my declaration? The scheduledTimerWithTimeInterval method instantiates and puts the timer on the main run loop. I'm also stopping the timer from selector method inside, so the timer as objects is used for sure. Sometimes in similar cases I break the line into two lines by declaring a type for variable on the first line and making assignment on the second line. But it is not a solution for timer object. Any suggestions? Here is my declaration and assigment:
NSTimer *levelScoreTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateTotalScoreLabelFromTimeLeftLabel:) userInfo:nil repeats: YES];
Change the code from
NSTimer *levelScoreTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateTotalScoreLabelFromTimeLeftLabel:) userInfo:nil repeats: YES];
to
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateTotalScoreLabelFromTimeLeftLabel:) userInfo:nil repeats: YES];
The compiler should be right, are you sure you’re not doing something wrong? Post more code. In each case you can mark the variable as unused:
__unused NSTimer *timer = …;
I use this for example in asserts that get compiled out in the production code and would lead to warnings:
__unused NSString *foo = …;
NSAssert(foo, #"Bar");
// foo no longer used
But in your case I’m almost sure the compiler is right. You say that you “stop the time from the selector method”, you mean from the method that is called when the timer fires? How do you get the pointer to the timer? Because you obviously store it in a local variable that won’t be available there.
You don't show enough of the rest of your code to see if you really use the value stored in levelScoreTimer anywhere. If this is a local variable, take a look in your method if you are assigning something else to it before you use the value you assign it above.
In my experience, the compiler knows such things better than we do. It doesn't miss or forget an assignment, retain or release, like we humans tend to do.
Consider doing this at appropriate place:
[levelScoreTimer invalidate];
levelScoreTimer = nil;
Referring from:
How do I use NSTimer?
Related
I have an NSTimer that I initialize with scheduledTimerWithTimeInterval: with a very short interval (.1 seconds) with no repeat, and then never use it again as it invalidates itself and therefore releases its retain on the target. Xcode warns that it is an unused variable, and I was curious if there was a sensible way to get rid of the warning (The yellow upsets my eyeballs!)
Thanks.
if you don't use it again don't save it in a variable.
[NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:#selector(timer:) userInfo:nil repeats:NO];
will work perfectly fine
Just don't assign the result to anything if you aren't going to use the return value.
[NSTimer scheduledTimerWithTimeInterval:...];
I've got a question about a NSTimer that i declared in the .h file and later set inside a method. But this method will be called more then ones, so the NSTimer runs multiple times under the same name.
Now my question is, is it possible to set a tag/id or whatever so i can invalidate the NSTimer with the correct tag/id?
Thanks for help!
This question was asked long ago, but since I had the same need today, here's my solution:
// set timer
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(whateverMethod)
userInfo:#"timer1"
repeats:YES];
To invalidate this same timer, check its userInfo string:
// invalidate timer
if ([[timer userInfo] isEqual:#"timer1"])
[timer invalidate];
If you're creating multiple NSTimers, and you care to handle them independently, you need to store them independently. If there are a fixed number, just create enough variables and name them appropriately. Or keep them in an array (which is then keyed by index). Or put them in a dictionary, keyed by some string name.
Your phrasing above ("runs under the same name") concerns me somewhat. Timers have some sensitive memory handling requirements. Edit your question with more details on what you're doing if you want broader design help.
You just have to save a reference to the NSTimer that you have created, and is running - and just use this reference.
Oke, i have now the following code. But is there nog way to set a unique ID/Tag so i can invalidate the timer on a later moment. This because the timer method will call more then ones. (its for animated images/buttons)
MainViewController.m
- (void)timerMethod {
NSTimer *daTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(animations:) userInfo:nil repeats:YES];
}
I'm writing an application that has a timer functionality built in. Unfortunately, I'm having problems with the NSTimer and I'm not sure what I'm doing wrong. Here is where I'm declaring the timer...
if(!myTimer)
{
NSLog(#"Setting up the timer!");
myTimer=[NSTimer timerWithTimeInterval:1
target:self
selector:#selector(timerTicked)
userInfo:nil
repeats:YES];
}
Thanks to the NSLog function, I know the code to set the timer up is going off, but it isn't calling the function:
-(void)timerTicked:(NSTimer*)theTimer
{
//NSLOG that tells me that this function isn't being fired
}
Anyone have any idea what I'm doing wrong?
Your missing a trailing colon on your selector name. Should be something like this
selector:#selector(timerTicked:)
-- added after questioner comment
If it still doesn't work, check to make sure you are adding the timer to a run loop
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSTimer_Class/Reference/NSTimer.html#//apple_ref/doc/uid/20000319-CHDECCEE
See the Discussion segment of the docs, it talks about how to add the timer to the run loop and points to the run loop docs, too.
Im using alot of timers in my application. For recording time, moving object, fading etc. I use the same timer for several puposes in the same view at different times. How should I declare and invalidate or release my timers properly?
Atm Im declaring the timers like this:
fadeTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(bortInfo) userInfo:nil repeats:YES];
and as soon as im not using it im doing this:
[fadeTimer invalidate];
fadeTimer = nil;
The retain count when im leaving the view is 0 on every timer. Should i release the timer in the dealloc aswell? My app runs quite good, but from time to time it crashes.
The clockTimer that i use for updating a label with the time uses
[[NSRunLoop mainRunLoop] addTimer:clockTimer forMode:NSRunLoopCommonModes];
Do i need to do anything with this mainLoop once i invalidate the clockTimer?
All in all please support me with some info about working with timers.
Thank you very much!
Joakim
You're not retaining your timers properly - if you want to refer to them again you should retain them. I'd do this with a property i.e. in your header file
#property (nonatomic, retain) NSTimer *fadeTimer;
and change your code to say
self.fadeTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(bortInfo) userInfo:nil repeats:YES];
// Put this whenever you want to remove your timer and in your dealloc method.
[fadeTimer invalidate];
self.fadeTimer = nil;
This will make sure that your timer is retained by your object. Otherwise you just have to hope that the timer stays around and doesn't get autoreleased by the iPhone. And as you say it's crashing occasionally, this might be the reason ;)
I'm afraid I don't know much about run loop but am confused why your don't just use a normal NSTimer to schedule things - why bother interacting with the run loop at all?
Scheduled timers are retained by the run loop, and retain their target. If you want to retain the timer, you have to jump through a few hoops to prevent a retain cycle (I wrote a non-retaining proxy class, which is a bit messy but it works).
Don't manipulate the run loop unless you know what you're doing (I don't). A "scheduled" timer is already added to the main run loop. If you're generating clockTimer like fadeTimer, then it's being added to the run loop twice.
"from time to time it crashes" doesn't help anyone. Run it in the debugger and see where it crashes. It might even print some messages to the console if you're lucky.
*also you can use and this is a better and optimize way to write this line
if (theTimer != nil) {
if([theTimer isValid]){
[theTimer invalidate];
}
theTimer = nil;
}*
I tracked down a memory leak with instruments. I always end up with the information that the responsible library is Foundation. When I track that down in my code, I end up here, but there's nothing wrong with my memory management:
- (void)setupTimer {
// stop timer if still there
[self stopAnimationTimer];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(step:) userInfo:nil repeats:YES];
self.animationTimer = timer; // retain property, -release in -dealloc method
}
the property animationTimer is retaining the timer. In -dealloc I -release it.
Now that looks like a framework bug? I checked with iPhone OS 3.0 and 3.1, both have that problem every time I use NSTimer like this. Any idea what else could be the problem?
(my memory leak scan interval was 0.1 seconds. but same thing with 5 seconds)
Do not call -[NSTimer dealloc]. Ever.
In this case, -scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: is balanced by -invalidate. You do not need to call -dealloc or -release on the timer object.
Unless your stopAnimationTimer method is invalidate'ing and release'ing (and then setting to nil) your animationTimer property, you're leaking memory.
I found it: I had a strong reference to my timer. The run loop retains it. So RC was 2. But because the Timer also holds a strong reference to the target (which in my case retained the timer), I had a deadlock situation. -dealloc was never ever called, and therefore my timer was never ever freed. WTF.