NSTimer code is executing forever - objective-c

Here is my code. I expected the timer to stop in 5 second after it starts but it doesn't. What is wrong here ?
-(void)loadView
{
NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:YES];
if([NSDate timeIntervalSinceReferenceDate] - startTime >= 5) {
[timer invalidate];
}
}
-(void)targetMethod:(NSTimer *)timer {
NSLog(#"bla");
}

NSDate's timeIntervalSinceReferenceDate is, by default, returning January 1st, 2001. Subtracting the same values will always be 0.
Apple's documentation:
https://developer.apple.com/library/mac/ipad/#documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/Reference/Reference.html
Here's an idea:
In your .h
#interface MyClass : NSObject
#property (nonatomic, retain) NSTimer *timer;
- (void)targetMethod:(NSTimer *)timer;
- (void)cancelTimer;
#end
In your .m
#implementation MyClass
#synthesize timer;
-(void)loadView
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:YES];
[self performSelector:#selector(cancelTimer) withObject:nil afterDelay:5.0];
}
-(void)cancelTimer {
[self.timer invalidate];
}
-(void)targetMethod:(NSTimer *)timer {
NSLog(#"bla");
}

This is short and simple:
NSDate *endtime = [NSDate dateWithTimeIntervalSinceNow:5];
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(timerTick:)
userInfo:endtime
repeats:YES];
-(void)timerTick:(NSTimer*)timer
{
NSLog(#"timer tick");
if ( [timer.userInfo timeIntervalSinceNow] < 0 )
{
[timer invalidate];
NSLog(#"invalidating timer");
}
}

Your time difference is always 0 so you never invalidate it!
Try setting startTime before you set the timer.

You get the 'startTime' value and the value you compare it to are identical. Your calculation will always give 0. You must store the 'startTime' in your loadView method and then use it in the calculation.

Related

Stop Method Execution after 5 Minute

How can i stop the execution of the method after a certain time?
I am calling method as below:
[NSTimer scheduledTimerWithTimeInterval:5.0f
target:self
selector:#selector(doSomeTask) userInfo:nil repeats:YES];
Here i have given interval of 5 Seconds. So this method will get called after every 5 seconds, So once the reaches to specified time i want to stop this method execution.
Take a counter variable, and increase in every call by 5 (as time interval is 5 sec ) like
counter = counter+5;
-(void) doSomeTask {
if (counter<=60) { // 5 min = 300 300/5 = 60
// Write method body here
counter = counter+5
}
else {
[timer invalidate];
}
}
If you want to stop execution of the method after 5 min. Then you can add code like this
#interface YourClass () {
int count;
}
#end
-(void)viewDidLoad {
count = 5;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:#selector(doSomeTask) userInfo:nil repeats:YES];
}
-(void) doSomeTask
{
count = count + 5;
if (count==300)
{
[timer invalidate];
timer=nil;
}
}
#define TIMER_LIFE_IN_SECONDS 300.0
#interface YourClass () {
NSTimeInterval _startTime;
}
self.timer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:#selector(doSomeTask) userInfo:nil repeats:YES];
_startTime = [NSDate timeIntervalSinceReferenceDate];
- (void) doSomeTask
{
// do thing
NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
if (now - _startTime > TIMER_LIFE_IN_SECONDS) {
[self.timer invalidate];
self.timer = nil;
}
}
you can try like this
NSTimer *reachTimer;
NSInteger secondsLeft;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
secondsLeft = 0;
reachTimer = [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
-(void)updateCounter:(NSTimer *)theTimer{
secondsLeft = secondsLeft+5;
if(secondsLeft>=300) // 60sec * 5min= 300
{
[reachTimer invalidate];
}
}
Try this;
int count;
NSTimer *timer;
-(void)startTimertillLimit:(int)limit {
count = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(doSomething:)
userInfo:[NSString stringWithFormat:#"%d",limit]
repeats:YES];
}
-(void)doSomething:(NSTimer*)sender
{
int limit = (int)[sender.userInfo intValue];
count = count + 5;
if (count > limit)
{
[timer invalidate];
timer=nil;
count = 0;
}
}
Try to create NSTimer that will be called after some time only once :
NSTimer *previous [NSTimer scheduledTimerWithTimeInterval:5.0f target:self selector:#selector(doSomeTask) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:300 target:self selector:#selector(stopPrevious) userInfo:nil repeats:NO];
-(void)stopPrevious{
[previous invalidate];
}

Objective C : NStimer- How to stop timer after n hours

I have started the timer using below call, and need to stop it after n hours
self.timer = [NSTimer scheduledTimerWithTimeInterval:20 target:self selector:#selector(sendLocationUpdates) userInfo:nil repeats:YES];
The solution I can thin of get the current time when timer start and keep adding time till threshold reaches. Or is there any better way to stop timer?
Add an instance variable to the class to store the start time of the timer:
YourClass.m:
#interface YourClass () {
NSTimeInterval _startTime;
}
#end
Record the current time when creating the timer:
self.timer = [NSTimer scheduledTimerWithTimeInterval:20 target:self selector:#selector(sendLocationUpdates) userInfo:nil repeats:YES];
_startTime = [NSDate timeIntervalSinceReferenceDate];
and test the current time in the sendLocationUpdates method:
#define TIMER_LIFE_IN_SECONDS 3000.0
- (void)sendLocationUpdates
{
// do thing
NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
if (now - _startTime > TIMER_LIFE_IN_SECONDS) {
[self.timer invalidate];
self.timer = nil;
}
}
simple solution
declare two properties
#property NSInteger counter;
#property NSTimeInterval interval;
set the counter to 0 before starting the timer
self.counter = 0;
self.interval = 20.0;
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval target:self selector:#selector(sendLocationUpdates) userInfo:nil repeats:YES];
in the sendLocationUpdates method increment the counter
- (void)sendLocationUpdates
{
counter++;
if (counter == 4 * (3600 / self.interval)) {
[self.timer invalidate];
self.timer = nil;
}
// do other stuff
}
with a given time interval of 20 seconds the timer fires 180 times per hour.
In the example the timer stops after 4 hours

How can I produce a blinking label

I want a label to be shown for 0.4 seconds and then hidden for 0.8 seconds - in an infinite loop.
How can I pull that off?
NSTimer and UIViews hidden property would be one possibility
I would say to use NSTimer. You could do it the following way:
Say your label is myLabel:
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
You should create a method to be called by NSTimer:
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE; //change comparassion to assing
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
else
{
self.myLabel.hidden = TRUE;
[NSTimer scheduledTimerWithTimeInterval:0.8
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
}
}
And initialize NSTimer somewhere like so:
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:#selector(changeLabelState:)
userInfo:nil
repeats:NO];
Note that you could also do the following:
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
- (void)changeLabelState:(NSTimer *)timer
{
if(self.myLabel.hidden == TRUE)
{
self.myLabel.hidden = FALSE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.4];
}
else
{
self.myLabel.hidden = TRUE;
[self performSelector:#selector(changeLabelState:) withObject:nil afterDelay:0.8];
}
}
Something Like the below.
In viewDidLoad:
NSTimer *silly = [NSTimer timerWithTimeInterval:0.4 target:self selector:#selector(question) userInfo:nil repeats:YES];
Function
-(void)question {
if(label.isHidden){
label.hidden = false;
} else {
label.hidden = true;
}
}
Make sure you have a UILabel defined in scope of this function and it should work. UNTESTED.

Using NSTimer, calling two functions with the same name, different parameters, both use scheduledTimerWithTimeInterval

I'm trying to write my own fade-ins and fade-outs using the AVAudioPlayer as a helper.
My problem is this: I have two method definitions with the same name, but one takes an int and the other takes no parameters. Is there a way for me to tell NSTimer which one to call? Couldn't really make sense of the documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nstimer_Class/Reference/NSTimer.html
-(void) stopWithFadeOut
{
if (_player.volume > 0.1) {
[self adjustVolume:-.1];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(stopWithFadeOut) userInfo:NULL repeats:NO];
}
else {
[self stop];
}
}
and
-(void) stopWithFadeOut:(NSString *)speed
{
int incr = [speed intValue];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(stopWithFadeOut) userInfo:NULL repeats:NO];
}
else {
[self stop];
}
}
Those actually have different names. The colon is significant, so the name (and hence the argument to #selector()) of the second method is stopWithFadeOut:.*
To create the timer, then, you want:
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(stopWithFadeOut:)
userInfo:NULL //^ Note! Colon!
repeats:NO];
However, this method is incorrect, because an NSTimer passes itself to its action method; it's not possible for you to pass in an arbitrary object. This is what the userInfo: parameter is for. You can sort of attach some object to the timer, and retrieve it inside the action method using the userInfo method, like so:
- (void)stopWithFadeOut: (NSTimer *)tim
{
NSString * speed = [tim userInfo];
int incr = [speed intValue];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(stopWithFadeOut:)
userInfo:speed
repeats:NO];
}
(Also note that this means your first method isn't really a correct NSTimer action method, because it doesn't have the NSTimer parameter.)
*The compiler wouldn't have let you declare or define two methods with the same name in one class, and the parameter type doesn't count as part of the selector, so trying to create -(void)dumblethwaite:(int)circumstance; and -(void)dumblethwaite:(NSString *)jinxopotamus; in one class doesn't work.
So this is what I came up with. Thanks Josh.
-(void) pauseWithFadeOut
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:0.1];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
}
-(void)fadeOut: (NSTimer*) deleg
{
int incr = (int) [deleg userInfo];
if (_player.volume > 0.1) {
[self adjustVolume:-incr];
}
}
-(void) pauseWithFadeOut:(NSString *)speed
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:[speed floatValue]];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
[self pause];
}
-(void) stopWithFadeOut
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:0.1];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
}
-(void) stopWithFadeOut:(NSString *)speed
{
NSNumber *incr = [[NSNumber alloc] initWithFloat:[speed floatValue]];
while (_player.volume > 0.1) {
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fadeOut) userInfo:incr repeats:NO];
}
[self stop];
}

Trouble with NSTimer

I am having so much trouble with NSTimers. I have used them before, but this timer just does not want to fire.
-(void) enqueueRecordingProcess
{
NSLog(#"made it!");
NSTimer *time2 = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(warnForRecording) userInfo:nil repeats:YES];
}
-(void) warnForRecording
{
NSLog(#"timer ticked!");
if (trv > 0) {
NSLog(#"Starting Recording in %i seconds.", trv);
}
}
I don't see why this won't run. I even tried this:
- (void)enqueueRecordingProcess
{
NSLog(#"made it!");
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(warnForRecording) userInfo:nil repeats:YES];
}
- (void)warnForRecording
{
NSLog(#"timer ticked!");
}
What is wrong?
Not sure if this fixes it but from the docs:
The message to send to target when the timer fires. The selector must have the following signature:
- (void)timerFireMethod:(NSTimer*)theTimer
The timer passes itself as the argument to this method.
I am not sure about you specifics, but you need to service the runloop in order to get events, including timers.
// Yes. Here is sample code (tested on OS X 10.8.4, command-line).
// Using ARC:
// $ cc -o timer timer.m -fobjc-arc -framework Foundation
// $ ./timer
//
#include <Foundation/Foundation.h>
#interface MyClass : NSObject
#property NSTimer *timer;
-(id)init;
-(void)onTick:(NSTimer *)aTimer;
#end
#implementation MyClass
-(id)init {
id newInstance = [super init];
if (newInstance) {
NSLog(#"Creating timer...");
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(onTick:)
userInfo:nil
repeats:YES];
}
return newInstance;
}
-(void)onTick:(NSTimer *)aTimer {
NSLog(#"Tick");
}
#end
int main() {
#autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}