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.
Related
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];
}
I have a problem: I want to NSTimer waiting until FLAG variable is YES, if FLAG = YES, myTimer is stop. How can i do that? I tried below code:
NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:#selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer timerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
[[NSApplication sharedApplication] runModalForWindow: scanningPanel];
This is resetAll () function :
-(void) resetAll: (NSTimer *) theTimer
{
if(FLAG)
{
NSLog(#"killWindow");
[[NSApplication sharedApplication] abortModal];
[scanningPanel orderOut: nil];
FLAG = NO;
}
else
{
delay +=6.0;
myTimer= [NSTimer timerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSModalPanelRunLoopMode];
[[NSApplication sharedApplication] runModalForWindow: scanningPanel];
}
}
I used 2 NSTimer, but only myTimer run, scanTimer not run. Please give me any suggestions. Thanks in advance
Why not use Key Value Observing for the FLAG change? Add the flag variable as a property of the class you're working in:
#property(nonatomic, assign) BOOL flag;
To avoid repetition place in your .m:
#define kFooFlagKey #"flag"
Override -setFlag: so it is KVO compliant:
-(void)setFlag:(BOOL)flag
{
if (_flag == flag) {
return;
}
[self willChangeValueForKey:kFooFlagKey];
_flag = flag;
[self didChangeValueForKey:kFooFlagKey];
}
In the class' initializer add self as the observer for the keypath you'd like to monitor. In this case it will be for the property "flag".
[self addObserver:self
forKeyPath:kFooFlagKey
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:NULL];
Don't forget to remove the observer in the class' -dealloc:
[self removeObserver:self forKeyPath:kFooFlagKey];
Create the timer to fire repeatedly (firingCallBack is a method called with each fire):
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.0f
target:self
selector:#selector(firingCallBack)
userInfo:nil
repeats:YES];
Implement KVO observing method:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:kFooFlagKey]) {
if (self.flag) {
[self performSelector:#selector(resetAll) withObject:nil afterDelay:0.0f];
}
}
}
Implement -resetAll however you'd like. It will be called when you are setting the flag variable via the accessor AND the flag is set to YES
Try like this:-
NSTimer *myTimer;
int delay = 6.0;
scanTimer= [NSTimer scheduledTimerWithTimeInterval:6.0 target:self selector:#selector(anotherfunc) userInfo:nil repeats:YES];
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[NSApp beginSheet:scanningPanel modalForWindow:[self window]
modalDelegate:self
didEndSelector:nil
contextInfo:self];
- (void)resetAll:(NSTimer *)theTimer
{
if (flag== YES)
{
[NSApp endSheet:scanningPanel];
[scanningPanel orderOut:self];
flag=NO;
}
else
{
delay +=6.0;
myTimer= [NSTimer scheduledTimerWithTimeInterval: delay
target:self
selector: #selector(resetAll:) userInfo:nil
repeats:NO];
[NSApp beginSheet:scanningPanel modalForWindow:[self window]
modalDelegate:self
didEndSelector:nil
contextInfo:self];
}
}
You just start the timer (already scheduled) and make it repeat at a relatively high frequency and stop it when the condition is met. One timer can act as two, like this:
- (void)startTimers {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
}
- (void)timerFired:(NSTimer *)timer {
if (self.stopTimerA && self.stopTimerB) {
[timer invalidate];
} else {
if (!self.stopTimerA)
[self timerAFired];
if (!self.stopTimerB)
[self timerBFired];
}
}
- (void)timerAFired {
// this can be coded like it has it's own timer
// we didn't pass the timer, so we can't invalidate it
// to stop...
self.stopTimerA = YES;
}
- (void)timerBFired {
// same idea here
}
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];
}
http://www.youtube.com/watch?v=5al6qqRzzQg when i click on the start more than once???
what will i need to do
#import "FirstViewController.h"
#implementation FirstViewController
-(IBAction)start;{
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop;{
[myticker invalidate];
}
-(IBAction)reset;{
time.text = #"0";
}
-(void)showActivity;{
int currentTime = [time.text intValue];
int newTime = currentTime + 1;
time.text = [NSString stringWithFormat:#"%d", newTime];
}
- (void)didReceiveMemoryWarning
Change your start and stop methods to this:
-(IBAction)start;{
[myticker invalidate];
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
}
-(IBAction)stop;{
[myticker invalidate];
myticker = nil;
}
That will stop it crashing. Also, you should add this:
-(void)dealloc
{
[myticker invalidate];
}
add a bool variable to the header of your class, like timerIsActive
-(IBAction)start;{
if (!timerIsActive) {
myticker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
timerIsActive = YES;
}
}
-(IBAction)stop;{
timerIsActive = NO;
[myticker invalidate];
}
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.