I'd like to keep track of how many times an NSTimer fires and store the number in an ivar. I have a pointer to an NSTimer stored in a property called timer that I've set like so: [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:#selector(method) userInfo:nil repeats:NO];
Any pointers out there on how to keep track of how many times timer fires and store the number in an instance variable?
Thanks.
Add an instance variable timerCount and then put timerCount++ into your timer method.
Related
I have an application that is supposed to log certain things every 1 second and I'm currently using NSTimer, but if my application transitions screens (or almost anything else, really) it slows down the timer a little bit making for inaccurate readings.
What is a reliable alternative to use? My current code is as follows:
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(update) userInfo:nil repeats:YES];
NSTimer is not guaranteed to fire exactly on time, ever. But you can use an NSTimer in a much more reliable way than you are now. When you use scheduledTimerWithTimeInterval you create an NSTimer which is scheduled in the run loop for NSDefaultRunLoopMode. This mode is paused when the UI is being used, so your timers won't fire when there is user interaction. To avoid this pause use the mode NSRunLoopCommonModes. To do this you will have to schedule the timer yourself like so:
timer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(update) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
You could:
Put the NSTimer in a different thread (it may not be affected by the UI that way)
Decrease the interval (say 0.1 second) and, in your logging function, check if it is the "right" time to log what you want.
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?
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];
}
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;
}*