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.
Related
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.
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'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;
}*
Here's the part of the code dealing with it:
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:1.0+index];
NSTimer *timer = [[NSTimer alloc] initWithFireDate:fireDate
interval:0.5
target:self
selector:#selector(countedtargetMethodGlow:)
userInfo:nil
repeats:NO];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[timer release];
But it's in a loop, so I'll be making a buncha these, and I don't know what I need to leave alone for the firing not to be messed up.
Every timer object you add to a run loop is retained by the run loop until it's invalidated (effectively indicating that the run loop is taking "ownership" of the timer while it needs it). So you can release any of those timers without affecting how they're scheduled on the run loop. If you need them for some independent purpose you should not release them, so they're guaranteed to still be around for you even if the run loop has finished with them.