Multiple timers set un in the same variable - ios

Is this code a problem?
self.UpdateTimer = [NSTimer scheduledTimerWithTimeInterval:60. target:self selector:#selector(update:) userInfo:nil repeats:YES];
I notice that this is in a method that is called often. However there is only one place where the timer is invalidated and set to nil ... the dealloc of that class.
Does setting a new timer multiple times automatically invalidate the old timer?

No, setting the timer to a new object does not invalidate the previous timer. You will end up with multiple timers running if you call that line of code multiple times, but only invalidate the currently referenced timer in one place elsewhere.
When you create the timer, you should probably check if one is already set and invalidate it before creating a new one.
if( self.UpdateTimer )
{
[self.UpdateTimer invalidate];
self.UpdateTimer = nil;
}
self.UpdateTimer = [NSTimer scheduledTimerWithTimeInterval:60. target:self selector:#selector(update:) userInfo:nil repeats:YES];
OR, simply leave the original one running, if you don't need to reset the timer interval.
if( !self.UpdateTimer )
{
self.UpdateTimer = [NSTimer scheduledTimerWithTimeInterval:60. target:self selector:#selector(update:) userInfo:nil repeats:YES];
}

Related

WebService Call after timeInterval

I want to my Webservice invoke once every 6 Hours.I am newer in iOS. Please help any help would be apperciated.I am stuck.
You can user NSTimer and schedule it for 6 hours
NSTimer *timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:6*60*60 //6 hour
target:self
selector:#selector(performAction)
userInfo:nil
repeats:YES];
you can call using NSTimer. this is automatically called which time you set.
e.g.
NSTimer *timer= [NSTimer scheduledTimerWithTimeInterval:10.0(your time) target:self selector:#selector(someMethod) userInfo:nil repeats:YES];
-(void)someMethod
{
////API called here...
}
In ViewDidLoad
NSTimer *timer = [NSTimer timerWithTimeInterval:360.0 target:self selector:#selector(hideandview) userInfo:nil repeats:YES];
-(void)hideandview
{
////API called here...
}
You should save the last time in prefence (NSUserDefaults) when you make a call.
Whenever the app starts. Start timer and check current time with last saved time and get the difference.

How to stop an NSTimer?

I have an NSTimer that I want to be stopped when I leave my vViewVontroller:
The timer is in a method that I call from viewWillAppear :
- (void) myMehtod
{
//timer = [[NSTimer alloc] init];
// appel de la methode chaque 10 secondes.
timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self selector:#selector(AnotherMethod) userInfo:nil repeats:YES];
//self.timerUsed = timer;
}
I call the method stopTimer in viewWillDisappear
- (void) stopTimer
{
[timer invalidate];
timer = nil;
}
PS: I tried the answer of user1045302 in this question but it didn't work:
How to stop NSTimer
The source of the problem probably is that myMehtod is called twice or more times.
Since the method does not invalidate existing timers before setting up the new one you actually have several timers ticking at the same time.
Fix is easy: invalidate old timers before setting up a new one:
- (void)myMehtod
{
[timer invalidate];
timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self
selector:#selector(anotherMethod)
userInfo:nil
repeats:YES];
}

Crash when checking if NSTimer isValid?

I am getting this exception in the console:
Error:
2015-06-25 23:12:01.841 Copyfeed for Mac[9512:584232]
-[_NSViewLayoutAux invalidate]: unrecognized selector sent to instance 0x6000001657c0
when checking if my timers are valid/and when invalidating them.
if ([_staticTimer isValid]) {
[_staticTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
if ([_selectionTimer isValid]) {
[_selectionTimer invalidate];
_selectionTimer =
[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
This is my new code:
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
#property (strong )NSTimer *staticTimer;
#property (strong )NSTimer *selectionTimer;
Now getting this error when I debug with zombie objects on.
2015-06-26 00:39:45.523 Copyfeed for Mac[11191:824502] ***
-[CFRunLoopTimer release]: message sent to deallocated instance 0x608000175e40
There are a couple of potential issues here.
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
What you are doing here is overriding the selectionTimer even though it might still contain a timer that is still scheduled in the run loop. So if you reset the property here, you should also make sure to call [_selectionTimer invalidate] before doing so.
Depending on what you are doing when the timer is firing, this could explain the crash on CFRunLoopTimer.
A general advice that turned out to be very helpful for me when working with NSTimer: I would recommend declaring all the properties that hold a scheduled timer as weak as they are retained by the run loop anyway. This way, you don't need to explicitly set them to nil after invalidating them but instead you can simply call invalidate every time you want to get rid of it and it will also automatically become nil once it has fired by the run loop, releasing all the data it might hold on to.
Note that this would still require you to call invalidate in case you want to cancel a timer or before replacing one, but you no longer need to set it to nil after doing so.
After you invalidate it, you should set an NSTimer object to nil.
invalidate method also does a release.
If you didn't do that, calling a method on it like isValid could cause your crash.
if (_selectionTimer != nil) {
[_selectionTimer invalidate];
_selectionTimer = nil;
// do something
}
Check here
if (_staticTimer != nil) {
[_staticTimer invalidate];
_staticTimer = nil;
//_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideHUD) userInfo:nil repeats:NO];
_staticTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideHUD) userInfo:nil repeats:NO];
}
From the documentation:
Because the run loop maintains the timer, from the perspective of
memory management there's typically no need to keep a reference to a
timer after you’ve scheduled it. Since the timer is passed as an
argument when you specify its method as a selector, you can invalidate
a repeating timer when appropriate within that method. In many
situations, however, you also want the option of invalidating the
timer—perhaps even before it starts. In this case, you do need to keep
a reference to the timer, so that you can send it an invalidate
message whenever appropriate. If you create an unscheduled timer (see
“Unscheduled Timers”), then you must maintain a strong reference to
the timer (in a reference-counted environment, you retain it) so that
it is not deallocated before you use it.
So you should make the timer weak instead of strong

How do I see if NSTimers are stacking and how to prevent it?

Im making an iphone game that uses NStimer for movement. I found out that there is a bug that makes the timers stack some times, but i havnt found out what causes is. Is there any way to see how many timers are allocated and is there any way to prevent it by doing something like this:
If(myTimer.numberOfAllocatedTimers == 0) {
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme) userInfo:nil repeats:YES];
}
Try this:
// use this to start timer
myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(doSthing) userInfo:nil repeats:YES];
// use this to stop timer
if (myTimer) {
[myTimer invalidate];
myTimer = nil;
}
A little more context on where this code is being used would be helpful.
However, I'll try to explain why it's happening anyway.
Every time you use [NSTimer scheduledTimerWithTimeInterval...], a new timer is created, and will start repeating. If your code creates a timer inside the callback method, see example below, you'll stack timers.
- (void)updateme {
if ([NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme) userInfo:nil repeats:YES]) {
// This creates stacked timers!
}
}
Here's how you should do it:
#property (nonatomic, strong) NSTimer *myTimer;
...
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(updateme:) userInfo:nil repeats:YES];
...
- (void)updateme:(NSTimer *)timer {
if (timer == self.myTimer) {
// Do something because the timers are equal
}
}

How to stop NSTimer at a specific point?

I've created a simple button game that gives the user a point with every tap of the button. The button randomly appears on screen every 1.5 seconds. I want the game to end after 30 seconds or after 20 random button pop ups. I've been using the code below to have the button randomly pop-up on the screen:
timer = [NSTimer scheduledTimerWithTimeInterval: 1.5 target:self
selector:#selector(moveButton:)
userInfo:nil
repeats:YES];
I've declared the timer in the header file:
NSTimer *timer;
#property (nonatomic, retain) NSTimer *timer;
I've read Apple Docs on Using Timers but fail to fully understand it. I thought maybe I could use:
- (void)countedTimerFireMethod:(NSTimer *)timer{
count ++;
if(count > 20){
[self.timer invalidate];
self.timer = nil;
But it does not work properly. What am I doing wrong? I'm new to objective-C so I'm not that familiar with how things work.
The problem is on your timer method you are passing moveButton method but in below method where you are stopping the timer that method name is different so try this:-
self.timer = [NSTimer
scheduledTimerWithTimeInterval: 1.5 target:self
selector:#selector(moveButton:)
userInfo:nil
repeats:YES];
//just change the method name below
- (void)moveButton:(NSTimer *)timer{
count ++;
if(count > 20){
[self.timer invalidate];
self.timer = nil;}
If you are using new version of Xcode then you don not need to declare
NSTimer *timer;
and when scheduling a timer you can use
self.timer = [NSTimer scheduledTimerWithTimeInterval: 1.5 target:self
selector:#selector(moveButton:)
userInfo:nil
repeats:YES]
instead of
timer = [NSTimer scheduledTimerWithTimeInterval: 1.5 target:self
selector:#selector(moveButton:)
userInfo:nil
repeats:YES]
You are using correct method to stop the timer i.e invalidate
You can also refer the link for more clarification.
Please let me know if you solve this problem through the above code.

Resources